前序知识
- 获取变量类型的语句是:
typeid(variable).name() ; - sizeof 是个关键字,在编译阶段起作用。
- sizeof 数组名,得到的是数组的字节大小。
指针与数组名的区别
- 数组和指针在编译器处理时是不同的,在运行时的表示形式也是不一样的,并可能产生不同的代码。对编译器而言,一个数组就是一个地址,而一个指针就是一个地址的地址。
- 数组名是不可修改的左值,不能直接对其赋值(定义时除外)。但可以用memcpy,strcpy等来进行间接“赋值”。
- “表达式中的数组名被编译器当作一个指向该数组第一个元素的指针。”
- "下标总是与指针的偏移量相同。
- “在函数参数的声明中,数组名被编译器当作指向该数组的第一个元素的指针。”(作为形参,数组名退化为指针)
- 数组作为sizeof()的操作数,显然此时需要的是整个数组的大小,而不是所指向第一个元素的大小
- 使用&操作符取数组的地址
- 数组是一字符串常量初始化值
验证
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;
(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]
一维数组
name | meaning | type |
---|
(arr2) | 数组名:指向第一行的指针(二维指针常量) | int [3] | (&arr2) | 一维数组的指针;(数组指针) | int (*)[3] | (arr2+1) | 数组指针+偏移;(指针) | int * | (*arr2) | 数组名解引用;(值) | int | (*arr2+1) | 数组名解引用+偏移;(值)(和下面一致;先解引用) | int | ((*arr2 )+1 | 数组名解引用+偏移;(值) | int |
二维数组
name | meaning | type |
---|
(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] |
若要快速得到一个二维数组最后一个元素的值可以这样
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
|