【踩坑记录】【C/C++】数组名与指针的关系;数组名取地址;数组名的解引用与取地址;

前序知识

  1. 获取变量类型的语句是:typeid(variable).name()
  2. sizeof 是个关键字,在编译阶段起作用。
  3. sizeof 数组名,得到的是数组的字节大小。

指针与数组名的区别

  • C专家编程 中有讲到,
  • 数组和指针在编译器处理时是不同的,在运行时的表示形式也是不一样的,并可能产生不同的代码。对编译器而言,一个数组就是一个地址,而一个指针就是一个地址的地址。
  • 数组名是不可修改的左值,不能直接对其赋值(定义时除外)。但可以用memcpy,strcpy等来进行间接“赋值”。
  • 讲到三个规定
  1. “表达式中的数组名被编译器当作一个指向该数组第一个元素的指针。”
  2. "下标总是与指针的偏移量相同。
  3. 在函数参数的声明中,数组名被编译器当作指向该数组的第一个元素的指针。”(作为形参,数组名退化为指针)
  • 讲到三个例外
  1. 数组作为sizeof()的操作数,显然此时需要的是整个数组的大小,而不是所指向第一个元素的大小
  2. 使用&操作符取数组的地址
  3. 数组是一字符串常量初始化值

验证

int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int arr2[3] = { 2,5,6 };
int(*p)[3] = &arr2;

cout << "(arr)		\t" << (arr) << " \t" << sizeof(arr) << "\t" << typeid(arr).name() << endl;
cout << "(arr + 1)  \t" << (arr + 1) << " \t" << sizeof(arr + 1) << "\t" << typeid(arr + 1).name() << endl;
cout << "(*arr)		\t" << (*arr) << " \t" << sizeof(*arr) << "\t" << typeid(*arr).name() << endl;
cout << "(*arr + 1)	\t" << (*arr + 1) << " \t" << sizeof(*arr + 1) << "\t" << typeid(*arr + 1).name() << endl;
cout << "(*(arr + 1))\t" << (*(arr + 1)) << " \t" << sizeof(*(arr + 1)) << "\t" << typeid(*(arr + 1)).name() << endl;
cout << "(&arr)		\t" << (&arr) << " \t" << sizeof(&arr) << "\t" << typeid(&arr).name() << endl;
cout << "(&arr+1)	\t" << (&arr + 1) << " \t" << sizeof(&arr + 1) << "\t" << typeid(&arr + 1).name() << endl;

cout << "*******************************************************************" << endl;

cout << "(arr2)		\t" << (arr2) << " \t" << sizeof(arr2) << "\t" << typeid(arr2).name() << endl;
cout << "(&arr2)	\t" << (&arr2) << " \t" << sizeof(&arr2) << "\t" << typeid(&arr2).name() << endl;
cout << "(arr2+1)	\t" << (arr2 + 1) << " \t" << sizeof(arr2 + 1) << "\t" << typeid(arr2 + 1).name() << endl;
cout << "(*arr2)	\t" << (*arr2) << " \t" << sizeof(*arr2) << "\t" << typeid(*arr2).name() << endl;
cout << "(*arr2+1)	\t" << (*arr2 + 1) << " \t" << sizeof(*arr2 + 1) << "\t" << typeid(*arr2 + 1).name() << endl;
cout << "((*arr2 )+1)\t" << ((*arr2) + 1) << " \t" << sizeof((*arr2) + 1) << "\t" << typeid((*arr2) + 1).name() << endl;
cout << "(p)	    \t" << (p) << " \t" << sizeof(p) << "\t" << typeid(p).name() << endl;
  • X86下结果
(arr)                   0117F834        36      int [3][3]
(arr + 1)       		0117F840        4       int (*)[3]
(*arr)                  0117F834        12      int [3]
(*arr + 1)              0117F838        4       int *
(*(arr + 1))    		0117F840        12      int [3]
(&arr)                  0117F834        4       int (*)[3][3]
(&arr+1)                0117F858        4       int (*)[3][3]
**********************************************
(arr2)                  0117F820        12      int [3]
(&arr2)         		0117F820        4       int (*)[3]
(arr2+1)                0117F824        4       int *
(*arr2)         		2       		4       int
(*arr2+1)               3       		4       int
((*arr2 )+1)    		3       		4       int
(p)             		0117F820        4       int (*)[3]

一维数组

  • int arr2[3] = { 1,2,3 };
namemeaningtype
(arr2)数组名:指向第一行的指针(二维指针常量)int [3]
(&arr2)一维数组的指针;(数组指针)int (*)[3]
(arr2+1)数组指针+偏移;(指针)int *
(*arr2)数组名解引用;(值)int
(*arr2+1)数组名解引用+偏移;(值)(和下面一致;先解引用int
((*arr2 )+1数组名解引用+偏移;(值)int

二维数组

  • arr[i][j]
namemeaningtype
(arr)数组名:指向第一行的指针;(二维指针常量)int [3][3]
(arr + 1)数组名+偏移;(指向一维数组的指针)int (*)[3]
(*arr)数组名解引用;(一维指针常量)int [3]
(*arr + 1)数组名解引用+偏移;(指针)int *
(*(arr + 1))数组名+偏移 +解引用;一维指针常量int [3]
(&arr)数组名取地址;(指向二维数组的指针)int (*)[3][3]
(&arr+1)数组名+偏移+取地址;(指向二维数组的指针)int (*)[3][3]
  • tips:

若要快速得到一个二维数组最后一个元素的值可以这样

int *ptr = (*int)(&arr + 1);
cout << *(ptr - 1) << endl;
  • arr只是arr[0]的地址,arr+1就是arr[1]的地址了.
  • &arr是整个arr[10]的首地址,是以整个数组为角度来看,虽然它与arr[0]的值相同,但是&arr+1就已经增加了10个int类型的字节的长度了.
    在这里插入图片描述
  • 即,对数组名取地址,得到的是数组名所指元素的地址。和指针不同;(编译器特性)

参考

【C专家编程】

https://blog.csdn.net/hmxz2nn/article/details/80157461

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值