[c/c++精选题目]07-指针和数组

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; // 110 110
	return 0;
}

分析:在fun()结束后,s仍然指向x。对p本身的改变,对s不变

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(ar)<<" "<<sizeof(s)<< endl; 40 4
3 int(*s)[10] = &p;这是错误的,不可以 大小相同,类型不同
4 int * (*s)[10] = &p;就可以了
在这里插入图片描述

能指向的三个条件:大小 类型 连续空间,

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;
}

这三种情况:编译器关心:数组大小 类型。其他情况下:都是首元素的地址

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;
}

在这里插入图片描述

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:

int a = 10, b = 20;
int const *p = &a;

int *s1 = p;   //error
int const *s2 = p;
int * const s3 = p; // error
const int * const s4 = p;

分析:第一个 第三个有错:能力扩大,通过解引用 进而改变*p的值

Note9:

int a = 10, b = 20;
int * const p = &a;

int *s1 = p;   
int const *s2 = p;
int * const s3 = p; 
const int * const s4 = p;

分析:都对。因为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个字节的空间。用于存放它引用变量的地址。

Note12:

数组名和指针的区别

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

Note13:

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;
}

在这里插入图片描述

Note14:

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

刘大望

谢谢你请的咖啡

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

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

打赏作者

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

抵扣说明:

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

余额充值