我们来谈谈表达式和类型。
除非它是 sizeof 或一元 & 运算符的操作数,或者是用于在声明中初始化另一个数组的字符串字面量,否则为“T 的 N 元素数组”类型的表达式被转换(“decays”)为“pointer to T”类型的表达式,表达式的值是数组第一个元素的地址。
表达式 arr 的类型为“double 的 3 元素数组的 2 元素数组”。在行中
printf( "%ld \n", (long) arr);
arr 不是& 或sizeof 运算符的操作数,因此将其转换为“指向double 的三元素数组的指针”类型的表达式,其值为第一个元素,或&arr[0]。
排队
printf( "%ld \n", (long) *arr);
由于表达式arr 的类型为“指向double 的三元素数组的指针”,因此表达式*arr(相当于表达式arr[0])的类型为“@987654338 的三元素数组@"。由于该表达式不是sizeof 或一元& 运算符的操作数,因此将其转换为“指向double”的类型的表达式,其值是第一个元素的地址,即@987654342 @。
在 C 中,数组的地址与数组的第一个元素的地址相同(没有为指向第一个元素的指针预留单独的存储空间;它是根据数组表达式本身计算的)。数组在内存中的布局为
+---+
arr: | 1 | 0x0x7fffe59a6ae0
+---+
| 2 | 0x0x7fffe59a6ae8
+---+
| 3 | 0x0x7fffe59a6aec
+---+
| 4 | 0x0x7fffe59a6af0
+---+
| 5 | 0x0x7fffe59a6af8
+---+
| 6 | 0x0x7fffe59a6afc
+---+
所以下面的表达式都会产生相同的值,但是类型会不同:
Expression Type Decays to
---------- ---- ---------
arr double [2][3] double (*)[3]
&arr double (*)[2][3] n/a
*arr double [3] double *
arr[i] double [3] double *
&arr[i] double (*)[3] n/a
*arr[i] 和 arr[i][j] 都产生 double 值。
那么现在让我们看看ptrptr:
double **ptrptr = (double **) arr;
printf( "%ld \n", (long) ptrptr);
printf( "%ld \n", (long) *ptrptr);
我们首先注意到ptrptr 不是数组表达式,所以上面的转换规则不适用。我们将它分配为指向arr 的第一个元素,但之后它的行为与任何其他指针一样,因此表达式ptrptr 和*ptrptr 将具有不同的值。由于ptrptr 指向数组的第一个元素(&arr[0][0]),*ptrptr 产生存储在第一个元素处的值,即1.00。碰巧的是,当您在此特定平台上将 1.00 的位模式解释为长整数时,它会显示为 4607182418800017408。
这里有一些代码可以让上面的内容更清楚一点:
#include <stdio.h>
int main( void )
{
double arr[][3] = {{1,2,3},{4,5,6}};
double **ptrptr = (double **) arr;
printf( " arr: %p\n", (void *) arr );
printf( " &arr: %p\n", (void *) &arr );
printf( " *arr: %p\n", (void *) *arr );
printf( " arr[0]: %p\n", (void *) arr[0] );
printf( "&arr[0]: %p\n", (void *) &arr[0] );
printf( " ptrptr: %p\n", (void *) ptrptr );
printf( "*ptrptr: %p (%f %ld)\n", (void *) *ptrptr,
*(double *) ptrptr, *(long int *) ptrptr );
return 0;
}
这是输出:
arr: 0x7fffe59a6ae0
&arr: 0x7fffe59a6ae0
*arr: 0x7fffe59a6ae0
arr[0]: 0x7fffe59a6ae0
&arr[0]: 0x7fffe59a6ae0
ptrptr: 0x7fffe59a6ae0
*ptrptr: 0x3ff0000000000000 (1.000000 4607182418800017408)
同样,*ptrptr 为我们提供了数组第一个元素的值,即1.0,但我们将该位模式解释为指针值 (0x3ff0000000000000) 和长整数 (@987654364 @)。