首页 > 编程语言 >C++学习路线(十四)

C++学习路线(十四)

时间:2024-10-15 14:46:38浏览次数:3  
标签:const int C++ 路线 地址 len str 十四 指针

指针的自增操作

查看数组与指针的关系

#include <iostream>
using namespace std;

int main() {
	int ages[] = { 18, 20, 22, 25, 28 };
	int len = sizeof(ages) / sizeof(ages[0]);
	cout << "使用数组的方式访问元素" << endl;
	for (int i = 0; i < len; i++) {
		cout << "第" << i + 1 << "个年龄是:" << ages[i] << endl;
	}
	cout << "使用指针的方式访问元素" << endl;
	int* p = ages;
	for (int i = 0; i < len; i++) {
		cout << "第" << i + 1 << "个年龄是:" << *p << endl;
		p++;
	}
	cout << "打印数组的地址 和 第一个成员的地址" << endl;
	cout << &ages << " " << &ages[0] << endl;
	return 0;
}

我们来探究下 指针自增操作

我们知道数组都是连续的内存组成的,如果说是int类型的话 ,第一块内存占四个字节 ,第二块占四个字节 ,所以说 我们地址访问的时候 是按照四个四个字节增加(int) , 但是为什么指针p是++就可以了呢,原因是 编译器做了优化 p++ 是 p = p + sizeof(int) * 1 也就是自动帮我们计算了int的字节,然后自增到p上面。

可以看到地址都是以4个字节递增的

练习一:让用户输入一个字符串,然后反向输出,注意:不能改变原来的字符串

第一种方法:

#include <iostream>
using namespace std;

#define MAX_SIZE 100
int main() {
	char str[MAX_SIZE];
	scanf_s("%s", str, MAX_SIZE);
	int len = strlen(str);
	for (int i = 0; i < len / 2; i++) {
		char temp = str[i];
		str[i] = str[len - i - 1];
		str[len - i - 1] = temp;
	}
	printf("%s", str);
	return 0;
}

第二种方法:

#include <iostream>
using namespace std;

#define MAX_SIZE 100
int main() {
	char str[MAX_SIZE];
	scanf_s("%s", str, MAX_SIZE);
	int len = strlen(str);
	for(int i = 0 ; i < len ; i ++ )
		printf("%c", str[len - 1 - i]);
	return 0;
}

第三种方法:

#include <iostream>
using namespace std;

#define MAX_SIZE 100
int main() {
	char str[MAX_SIZE];
	scanf_s("%s", str, MAX_SIZE);
	int len = strlen(str);
	char* p = &str[len - 1];
	for(int i = 0 ; i < len ; i ++ )
		printf("%c", *p--);
	return 0;
}

指针与整数的加减

1)指针与整数的运算,指针加减数字表示的意义是指针在数组中位置的移动:对于整数部分而言,它代表的是一个元素,对于不同的数据类型,其数组的元素占用的字节是不一样的,
比如指针 +1,并不是在指针地址的基础之上加1个地址,而是在这个指针地址的基础上加1个元素占用的字节数:
如果指针的类型是char*,那么这个时候1代表1个字节地址;如果指针的类型是int*,那么这个时候1代表4个字节地址;如果指针的类型是 foat*,那么这个时候1代表4个字节地址;如果指针的类型是 double*,那么这个时候1代表8个字节地址。

const和指针

int a = 1;

const int * p = &a;

 上面的 const int *p =  &a; 代表了 常量指针, const关键字代表了告诉编译器,通过这个指针所访问的数据不能被修改。在这个例子中,int 前面的 const 表示这个指针指向的整数是只读的,不能通过该指针来改变它的值。

int numbers = 10 , numbers2 = 20;
const int *ptr = &numbers;
//修改指针指向的地址
ptr = &numbers2;
//修改执政指向的地址的值
*ptr = 30;

int a = 1;

int * const p = &a;

int numbers = 10 , numbers2 = 20;
 int * const ptr = &numbers;
//修改指针指向的地址
ptr = &numbers2;
//修改执政指向的地址的值
*ptr = 30;

 

我们进行一下总结

const int * p = &a; 可以改变所指向的地址 但是不能改变所指向地址的值

int* const p = &a; 可以改变所指向地址的值 但是不能改变所指向的地址

 看const 离类型(int)近,还是离指针变量名近,离谁近,就修饰谁,谁就不能变

二级指针

二级指针也是普通的指针变量,只不过二级指针能够访问的值*ptr 是一个地址。

#include <iostream>
using namespace std;

int main() {
	//柜子2的值是100
	int guizi2 = 100;
	//柜子1的值存的是柜子2的地址
	int *guizi1 = &guizi2;
	//张三的值是柜子1的地址
	int** zhangsan = &guizi1;
	cout << "柜子2的值:" << guizi2 << " 柜子2本身的地址:" << &guizi2 << endl;
	cout << "柜子1的值:" << guizi1 << " 柜子1本身的地址:" << &guizi1 << endl;
	cout << "张三的值:" << zhangsan << " 张三本身的地址:" << &zhangsan << endl;
	return 0;
}

我们把上面打印出来的值进行一个整理

二级指针的用途

一级指针和二级指针

一级指针:当你有一个指针指向一个变量的内存地址时,这被称为一级指针。当你把一个变量的地址(也就是指针)作为参数传递给一个函数时,你可以在该函数内部修改这个变量的值,并且这个改变会影响到原始数据,因为你是直接操作的内存地址。但是,当函数执行完毕后,你在函数内部创建的任何局部变量都无法通过这个指针带出函数外使用

void updateNum(int *p) {
    *p = 20; // 通过 p 修改了 p 指向的值,即 num
}

上面可以通过传入一个指针,修改指针指向的值。但是p指向一个局部变量的时候,当作用域结束后,localVal被清理掉 p指向了一个垃圾地址。

void badFunction(int *p) {
    int localVar = 30; // 局部变量
    p = &localVar;     // 尝试修改 p 指向局部变量
}

调用 badFunction(&num);
这样做是无效的,因为 localVar 在函数结束时不再存在

我们再举一个例子,我们传入一个指针 让指针指向局部的静态变量,然后打印值,这种报错了,局部变量的地址一旦传递出其所在的作用域就变得无效。因此,boy_home 返回后,试图使用 p 是未定义的行为。 

简化一下:因为p指针传入的是一个副本 也就是形参的p和实参的p是两个不同的变量 所以说 p=&count 是形参的变量的值赋值为count的地址 但是外面的还是NULL

#include <iostream>
using namespace std;
void boy_home(int* p) {
	static int count = 23;
	p = &count;
}
int main() {
	int* p = NULL;
	boy_home(p);
	cout << "p = " << *p << endl;
}

所以我们必须使用二级指针 也就是说 int** p 接受的是形参一级指针p的地址 也就是说**p的指针可以访问到实参的一级指针,使用*p访问到实参的一级指针。

#include <iostream>
using namespace std;
void boy_home(int** p) {
	static int count = 23;
	*p = &count;
}
int main() {
	int* p = NULL;
	boy_home(&p);
	cout << "p = " << *p << endl;
}

下面是二级指针的另外一个例子 

#include <iostream>
#include <stdlib.h>
using namespace std;

void goodFunction(int **p) {
	int* localPtr = (int*)malloc(sizeof(int));
	if (localPtr == NULL) {
		cout << "Memory allocation failed" << endl;
		exit(1);
	}
	*localPtr = 100;
	*p = localPtr;
}

int main() {
	int* num = NULL;
	goodFunction(&num);
	if (num != NULL) {
		cout << "The value of num is " << *num << endl;
		free(num);
	}
	return 0;
}

标签:const,int,C++,路线,地址,len,str,十四,指针
From: https://blog.csdn.net/weixin_45169583/article/details/142915481

相关文章

  • C++学习路线(十五)
    多级指针#include<iostream>usingnamespacestd;intmain(){ intblock1=888; int*block2=&block1; int**block3=&block2; int***block4=&block3; int****block5=&block4; cout<<"block2:"<<*block2......
  • Ubuntu中VSCode配置CC++环境
    我的环境:Ubuntu22.04.5LTSVSCode版本:1.94.2参考文章:https://blog.csdn.net/zimuzi2019/article/details/106861692https://zhuanlan.zhihu.com/p/147366852一、安装gcc/g++和gdbsudoapt-getupdatesudoapt-getinstallgccsudoapt-getinstallg++sudoa......
  • day03(C++)信号槽
    目录1.概念2.函数原型3.连接方式3.1自带信号→自带槽3.2自带信号→自定义槽3.3自定义信号4.信号槽传参5.对应关系5.1一对多5.2多对一信号槽1.概念之前的程序界面只能看,不能交互,信号槽可以让界面进行人机交互。信号槽是Qt在C++基础上新增的......
  • RBE104TC C/C++ Programming Language
    RBE104TCC/C++ProgrammingLanguageAssignment1ContributiontotheOverallMarks30%IssueDateSubmissionDeadline13thOctober2024AssignmentOverview:ThisassignmentisgearedtowardsassessingfundamentalcodingconceptsinC/C++andinitiatingthep......
  • c++基础语法知识
    基础当VS中一个项目下有两个及以上的源文件时,编译会产生错误:main已经在test.obj中定义;找到一个或多个多重定义的符号。**解决办法:**将不需要编译的源文件排除:右键“属性”,将“从生成中排除”选择“是”,保存后再运行需要运行的源文件就可以成功,且被排除的文件右下角有红标......
  • C++面试速通宝典——27
    504.孤儿进程和僵尸进程是什么?怎么处理?孤儿进程:当一个父进程结束,而他的一个或多个子进程还在运行时,那些子进程将成为孤儿进程。孤儿进程会被init进程(进程ID为1)自动领养,init进程会负责调用wait()来收集他们的退出状态。僵尸进程:当一个子进程结束,在其父进程没有调用wait()......
  • C++试题带答案
    一、选择填空题1.有如下定义structperson{char name[9];intage;};person  pr[10]={"Johu",17,"Paul",19,"Mary",18,"Adam",16};根据上述定义,能输出字母M的语句是     A)cout<<pr[3].mane;          B)cout<<pr[3].name[1];C......
  • 【C++指南】C++中的浅拷贝与深拷贝:深入剖析
              ......
  • 网络安全系统教程+渗透测试+学习路线(自学笔记)_渗透测试工程师怎么自学
    一、什么是网络安全网络安全可以基于攻击和防御视角来分类,我们经常听到的“红队”、“渗透测试”等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。无论网络、Web、移动、桌面、云等哪个领域,都有攻与防两面性,例如Web安全技术,既有Web渗透,也......
  • 网络安全自学入门:(超详细)从入门到精通学习路线&规划,学完即可就业_网络安全自学路线
    很多人上来就说想学习黑客,但是连方向都没搞清楚就开始学习,最终也只是会无疾而终!黑客是一个大的概念,里面包含了许多方向,不同的方向需要学习的内容也不一样。算上从学校开始学习,已经在网安这条路上走了10年了,无论是以前在学校做安全研究,还是毕业后在百度、360从事内核安全产......