指针和引用区别 数组名和指针的区别

该博客围绕指针和数组名展开。介绍了指针的两个值,分析了函数结束后指针指向的变化;阐述了数组名在取地址、初始化引用等方面的例外情况;还讲解了二级指针的存储特点,以及指针和数组名在使用和汇编层面的区别等信息技术相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Note1:指针有两个值:P 和*P

void fun(int *p)//形参 不分配空间
{
	*p += 100;
	int a = 10;
	p = &a;
}
int main()
{
	int x = 10;
	int *s = &x;
	fun(s);
	cout << *s <<endl<< x;
	return 0;
}

在这里插入图片描述
分析:在fun()结束后,s仍然指向x。对p本身的改变,对s不变。
在这里插入图片描述
p=&a;后 p指向a的地址。 s仍是x的地址,并未改变。
###################################################################
Note2:

void Swap_a(int a,int b)//传值操作:形参改变,但是实参不变
{
	int c = a;
	a = b;
	b = c;
}
void Swap_b(int &a,int &b)//传入引用:可以改变实参
{
	int c = a;
	a = b;
	b = c;
}
void Swap_c(int *p1,int *p2)
{
	int c = *p1;
	*p1 = *p2;
	*p2 = c;
}
int main()
{
	int x = 10, y = 20;
	Swap_a(x, y);
	cout << x << " " << y << endl;         //NO
	Swap_b(x, y);
	cout << x << " " << y << endl;         //YES
	Swap_c(&x, &y);
	cout << x << " " << y << endl;         //YES

	return 0;
}

###################################################################
Note3:数组名的第二个例外:取地址

int main()
{
	int a = 10;
	int ar[] = { 12, 23, 34, 45, 56, 67, 78, 89, 90, 100 };
	cout << sizeof(ar) << endl;//数组名的第一个例外:40

	//1 从右到左。2 遇见(),先内后外
	int *p[10];//[10]数组,放的是整型指针    p是数组名,数组开辟10个大小空间
	int *r = &a;
	int(*s)[10] = &ar;//(*s)指针(开辟4个字节,存放数组地址),指向的数组:开辟10个大小,里面放的是整型类型   这个10 不可以少,和ar保持一致
	return 0;
}

1 p和ar的区别:p数组放的是 整型指针(四个字节)。
2 cout << sizeof§ <<" "<<sizeof(s)<< endl; 40 4
3 int(*s)[10] = &p;这是错误的,不可以 大小相同,类型不同
4 int * (*s)[10] = &p;就可以了
5

6 能指向的三个条件:大小 类型 连续空间。
###################################################################
Note4:数组名的第三个例外:初始化引用,让这个引用代表整个数组

int main()
{
	int ar[] = { 12, 23, 34, 45, 56, 67, 78, 89, 90, 100 };
	cout << sizeof(ar) << endl;//数组名的第一个例外:40

	int &br1 = ar[0];//12的别名
	int(&br2)[10] = ar;//数组ar的引用

	int *p[10];//[10]数组,放的是整型指针    p是数组名,数组开辟10个大小空间
	int(*s)[10] = &ar;//(*s)指针(开辟4个字节,存放数组地址),指向的数组:开辟10个大小,里面放的是整型类型
	int* (&br3)[10] = p;//数组p的引用
	return 0;
}

这三种情况:编译器关心:数组大小 类型。
其他情况下:都是首元素的地址
int &cr[10]; 不能编译通过,产生二义性。
###################################################################
Note5:二级指针:
二级指针存储一级指针地址,一级指针存储变量地址。上低下高,地址连续。

int main()
{
	int a3 = 0, a2 = 0, a1 = 0, a0 = 0;
	int *p3 = &a3, *p2 = &a2, *p1 = &a1, *p0 = &a0;
	int **s = &p0;
	
	return 0;
}

在这里插入图片描述
一级指针:
type *p=0;
p+=1;//p+=sizeof(type)*1;

二级指针:
type *s;//二级指针
s+=1;//s+=sizeof(type
)*1; 4
*s+=1;//*s+=sizeof(type)1; //此时s 是一级指针 类型可能会变
###################################################################
Note6:

int main()
{
	int ar0[3][4] = { 0 };
	int(*s)[4] =ar0;//   s是二级指针   s+1是加一个数组  s指向数组的地址
	cout << "ar0[2][2]:" << ar0[2][2] << endl;
	*(*(s + 2) + 2) = 1;
	cout << "ar0[2][2]:" << ar0[2][2] << endl;
	return 0;
}

在这里插入图片描述
ar0 数组首元素地址 ar0+1加到下一个元素
&ar0 数组的地址 &ar0+1加到下一个数组
*&ar0 数组首元素地址
###################################################################
Note7:

void fun(int &a)
{
	int *p = &a;
	a += 10;
	*p += 10;
}
int main()
{
	int x = 10;
	int &r = x;
	fun(x);
	fun(r);
	cout << x << endl;//50
	return 0;
}

运行结果:
在这里插入图片描述
###################################################################
Note8:
在这里插入图片描述
分析:第一个 第三个有错:能力扩大,通过解引用 进而改变*p的值。
###################################################################
Note9:
在这里插入图片描述
分析:都对。因为p的值是 a的地址,s1 s2 s3的值都可以改变,而且其指向的值也可以变,p的值不受影响。
###################################################################
Note10:对应于 Note7。引用被编译器处理为 自身不可改变的 指针

void fun(int * const a)//用指针模拟逻辑上的引用
{
	int *p = a;
	*a += 10;
	*p += 10;
}
int main()
{
	int x = 10;
	int * const r = &x;
	fun(&x);
	fun(r);
	cout << x << endl;//50
	return 0;
}

这个不可改变的指针 在使用时(使用引用),常常解引用操作。
###################################################################
Note11:

	int c = 10;
	int &b = c;
	int *p = &c;
	b = 100;
	*p = 100;

反汇编:
int c = 10;
00E646B2 mov dword ptr [c],0Ah
int &b = c;
00E646B9 lea eax,[c]
00E646BC mov dword ptr [b],eax
** int *p = &c; **
00E646BF lea eax,[c]
00E646C2 mov dword ptr [p],eax
b = 100;
00E646C5 mov eax,dword ptr [b]
00E646C8 mov dword ptr [eax],64h
*p = 100;
00E646CE mov eax,dword ptr [p]
00E646D1 mov dword ptr [eax],64h

引用也开辟4个字节的空间。用于存放它引用变量的地址。
###################################################################
Note11:数组名和指针的区别:

int main()
{
	int ar[10] = { 1, 2, 3, 4 };
	int *p = ar;
	p[1] = 6;//   *(p+1)
	ar[1] = 6;//   *(ar+1)
	return 0;
}

分析:
p[1] = 6;
00F24BDE mov eax,4
00F24BE3 shl eax,0
00F24BE6 mov ecx,dword ptr [p] //先从内存中访问p
00F24BE9 mov dword ptr [ecx+eax],6
ar[1] = 6;
00F24BF0 mov eax,4
00F24BF5 shl eax,0
00F24BF8 mov dword ptr ar[eax],6
###################################################################
Note12:

int main()
{
	int ar[5][2] = { 1,2,3,4,5,6,7,8,9,10 };
	int(*p)[2] =&ar[1];//    p是指向数组的指针
	cout << p[1][3] << endl;
	int *s = ar[1];//     *(ar+1)
	cout << s[3] << endl;
	return 0;
}

在这里插入图片描述
###################################################################
Note13:

int main()
{
	int ar[3][4];
	sizeof(ar);//12*4
	int(*p)[3][4] = &ar;//p是指向二维数组的地址 p+1是48
	int(&br)[3][4] = ar;
	int(*s)[4] = ar;//s指向一位数组的地址   ar的首元素是个一位数组
	return 0;
}

###################################################################
Note14:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤傲小二~阿沐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值