在此代码中:
#include<stdio.h>
int main()
{
int num[2] = {20, 30};
printf("%d", num);
printf("%d", &num[0]);
return 0;
}
据我所知,两个printf语句都会打印num
中第一个元素的地址,因为在第一个语句中,num
是一个指向int的指针.
但是如果 num
是一个指针,那么它也应该有任何地址,但在打印其地址时(使用 printf("%d", &num)
),它是显示第一个元素的地址。
在二维数组中,整个事情也变得困惑:
#include<stdio.h>
int main(void)
{
int num[ ] [2]={20,30,40,50};
printf("%d",*num);
return 0;
}
该程序正在打印第零个元素的地址,即num[0][0]
的地址。但它为什么要这样做呢?为什么它不打印存储在其中的值,因为它们都有相同的地址(num,num[0]
和 num[0][0]
)?
最佳答案
要事第一;数组变量不是指针;它们不存储任何东西的地址。
对于诸如这样的声明
T a[N];
内存将布局为
+---+
a[0]: | |
+---+
a[1]: | |
+---+
...
+---+
a[N-1]: | |
+---+
对于 2D MxN 数组,它看起来像
+---+
a[0][0]: | |
+---+
a[0][1]: | |
+---+
...
+---+
a[0][N-1]: | |
+---+
a[1][0]: | |
+---+
a[1][1]: | |
+---+
...
+---+
a[M-1][N-1]: | |
+---+
对于 3D 和更高维的数组,该模式应该是明显的。
如您所见,没有为包含第一个元素的地址的单独变量a
预留存储空间;相反,C 语言中有一条规则,类型为“T
的 N 元素数组”的表达式将被转换(“衰变”) ") 到“指向 T
”类型的表达式,表达式的值将是数组第一个元素的地址,除非当数组表达式为以下之一:
sizeof
运算符的操作数- 一元
&
运算符的操作数 _Alignof
运算符的操作数(C99 及更高版本)- 用于在声明中初始化数组的字符串文字
因此给出声明
T a[N];
以下所有内容均正确:
Expression Type Decays to Value
---------- ---- --------- -----
a T [N] T * address of first element, &a[0]
*a T n/a value stored in first element
&a T (*)[N] n/a address of the array, which is
the same as the address of the
first element of the array
a[i] T n/a value stored in the i'th element
&a[i] T * n/a address of the i'th element
sizeof a size_t n/a total number of bytes used by the
array
sizeof *a size_t n/a total number of bytes used by the
first element of the array
sizeof &a size_t n/a total number of bytes used by a
pointer to the array
表达式a
的类型为“T
的N元素数组”;它不是一元 &
或 sizeof
运算符的操作数,因此它被转换为指向数组第一个元素的指针,amd 它的值是该元素的地址元素。
表达式&a
的类型为“指向T
的N元素数组的指针”;由于 a
是一元 &
运算符的操作数,因此不应用上面的转换规则(这就是表达式具有类型 T (*)[N ]
而不是 T **
)。但是,由于数组的地址与数组第一个元素的地址相同,因此它产生与表达式 a
相同的值。
表达式&a[0]
的类型为“指向T
的指针”,并显式指向数组的第一个元素。同样,该值将与前两个表达式相同。
对于二维数组
T a[M][N];
以下所有内容均正确:
Expression Type Decays to Value
---------- ---- --------- -----
a T [M][N] T (*)[N] address of first subarray, a[0]
*a T [N] T * address pf first subarray, a[0]
&a T (*)[M][N] n/a address of the array, which is
the same as the address of the
first subarray, which is the same
as the address of the first element
of the first subarray.
a[i] T [N] T * address of first element of i'th
subarray
*a[i] T n/a value of first element of i'th subarray
&a[i] T (*)[N] n/a address of the i'th subarray
sizeof a size_t n/a total number of bytes used by the
array
sizeof *a size_t n/a total number of bytes used by the
first subarray
sizeof &a size_t n/a total number of bytes used by a
pointer to the array
最后一点:要打印指针值,请使用 %p
转换说明符并将参数强制转换为 (void *)
(这几乎是唯一一次将指针显式转换为 void *
被认为是正确的):
printf( " &a yields %p\n", (void *) &a );
printf( " a yields %p\n", (void *) a );
printf( "&a[0] yields %p\n", (void *) &a[0] );
编辑
回答评论中的问题:
num,num[] and num[][] are all different thing. There types are different.Here num decays and became pointer to a pointer and num[] decays and became pointer to int and num[][] is a int. Right?
不完全是。
假设声明如下
int arr[10][10];
然后表达式arr
将衰减为类型int (*)[10]
(指向int
的10个元素数组的指针),不是 int ** ;再次引用上表。否则你是对的; arr[i]
将衰减为 int *
类型,并且 arr[i][j]
将具有 int
类型>。
“T
的 N 元素数组”类型的表达式衰减为“指向 T
的指针”类型;如果 T
是数组类型,则结果是“指向数组的指针”,而不是“指向指针的指针”。
关于c - 为什么 *num 不显示第零个元素值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26588906/