C++ 将数组名解释为其第一个元素的地址,而对数组名应用地址运算符时,得到的是整个数组的地址。从数字上而言,这两个地址相同,无需区分;但从概念上特别是需要运用指针算术时,需要明白两者的区别。如下示例中假设 short
宽 2 字节,系统为 32 位,数组首地址为0x0028ccf0,指针变量 ptr
和 ptrc
的区别如下:
ptr
的类型是 short*
,存储的是一个 2 字节内存块的地址,它指向的对象是 short
类型,记号 *ptr
与 tacos[0]
等价。ptrc
的类型是 short(*)[10]
,存储的是一个 20 字节内存块的地址,它指向的对象是包含 10 个元素的 short
数组,记号 *ptrc
与 tacos
等价。表示 tacos
、&tacos
、&tacos[0]
的区别如下:
tacos
和 &tacos[0]
等效,类型都为 short *
,存储的是一个 2 字节内存块的地址,它们指向的对象是 short
类型,但在运用 sizeof()
时,这两者会有区别,sizeof(tacos)=20
而 sizeof(&tacos[0])=4
。&tacos
的类型为 short(*)[10]
,存储的是一个 20 字节内存块的地址,它指向的对象是包含 10 个元素的 short
数组。//声明并初始化数组
short tacos[10] = {5,2,8,4,1,2,2,4,6,8};
//声明并初始化指针一:以下几种赋值结果对ptr等效
short *ptr = tacos; //值为0x0028ccf0
short *ptr = &tacos[0]; //值为0x0028ccf0
//声明并初始化指针二
short (*ptrc)[10] = &tacos;//值为0x0028ccf0
//访问数组第三个元素
cout << tacos[2]; //结果为8
cout << *(tacos+2); //结果为8
cout << ptr[2]; //结果为8
cout << *(ptr+2); //结果为8
cout << (*ptrc)[2]; //结果为8
cout << *(*ptrc+2); //结果为8
//应用指针算术时单位1表示的字节数
cout << int(tacos+1)-int(tacos); //结果为2
cout << int(&tacos[0]+1)-int(&tacos[0]);//结果为2
cout << int(&tacos+1)-int(&tacos); //结果为20
cout << int(ptr+1)-int(ptr); //结果为2
cout << int(ptrc+1)-int(ptrc); //结果为20
//应用sizeof()获得内存量大小
cout << sizeof(tacos); //结果为20
cout << sizeof(&tacos[0]);//结果为4
cout << sizeof(&tacos); //结果为4
cout << sizeof(tacos[0]); //结果为2
cout << sizeof(ptr); //结果为4
cout << sizeof(ptrc); //结果为4
上述例子中数组名tacos
和指针变量ptrc
以及ptr
的区别如下:
tacos
是常量,值不能修改;ptrc
以及ptr
是变量,值可以修改。tacos
使用sizeof()
得到的是整个数组的内存量宽度;对ptrc
以及ptr
使用sizeof()
得到的是指针变量的内存量宽度。实际上,上述访问方式中,C++ 编译器会自动将 tacos[2]
转换为*(tacos+2)
,将ptr[2]
转换为*(ptr+2)
,将(*ptrc)[2]
转换为*(*ptrc+2)
,前者称为数组表示法,后者称为指针表示法。