有人可以通过将指针和双指针添加到其名称来解释如何通过它的名称引用数组,如下面的代码所示:
#include<stdio.h>
main()
{
int a[3][2];
a[0][0]=15;
a[0][1]=150;
a[1][0]=115;
a[1][1]=165;
a[2][0]=135;
a[2][1]=139;
printf( "%u\n", a);
printf( "%u\n", *a);
printf( "%u\n", **a);
}
答案 0 :(得分:5)
第一个
printf("%u\n",a);
打印a
的地址,该地址与第一个元素的地址相同。
第二个
printf("%u\n",*a);
取消引用a
并提供a
的第一行“
和第三个
printf("%u\n",**a);
取消引用指向a
的第一个“行”的指针,并给出此二维数组中第一个元素的值。
当您在打开警告的情况下编译示例时,编译器已经会抱怨并告诉您使用的某些类型。当您将指针作为printf
的参数时,应使用格式说明符%p
printf("%p\n",a);
printf("%p\n",*a);
格式说明符%u
适用于unsigned int
,如果您有int
,则最好使用说明符%d
printf("%d\n",**a);
答案 1 :(得分:3)
a
和*a
都是指针,因此在格式化输出中将其打印为printf()
使用%p
作为格式说明符。
否则,编译器会收到警告消息
warning: format ‘%x’ expects type ‘unsigned int’, but argument 2 has type ‘int (*)[2]’
warning: format ‘%x’ expects type ‘unsigned int’, but argument 2 has type ‘int *’
所以试试这个:
printf("%p\n",a);
printf("%p\n",*a);
第三种情况**a
的属于int
类型,因此最好使用%d
或%i
printf("%d\n",**a);
根据C标准,
ISO c99 standard : 7.19.6 Formatted input/output functions
9 If a conversion specification is invalid, the behavior is undefined.
If any argument is not the correct type for the corresponding conversion
specification, the behavior is undefined.
答案 2 :(得分:0)
就像a是地址而不是* a是
的值
答案 3 :(得分:0)
除非它是sizeof
,_Alignof
或一元&
运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字, >“{元素数组T
”类型的>表达式将被转换(“衰减”)为“指向T
的指针”类型的表达式,表达式的值将是数组第一个元素的地址。
在第一个printf
调用中,表达式a
具有类型为“{element}的2元素数组的3元素数组”;根据上面的规则,表达式将转换为“指向int
的{2}元素数组的指针”(int
),其值与int (*)[2]
相同。
在第二次&a[0]
调用中,表达式printf
的类型为“{element}}的2元素数组”;根据上面的规则,表达式将转换为“指向*a
”(int
)的类型,其值将与int
相同(与{{ 1}} - 数组的第一个元素的地址与数组本身的地址相同。
在第三次int *
调用中,表达式&a[0][0]
的类型为&a[0]
,其值为printf
存储的值(本例中为15)。
答案 4 :(得分:0)
对类型的检查是有益的。
a
具有类型int [3][2]
,即包含3个2个整数的数组的数组。但是,无法在C中分配或传递数组类型。将a
传递给printf
时发生的事情是将降级为指向其第一个参数的指针,即{ {1}},其类型为&a[0]
,即指向2个整数的数组的指针。那是你看到的地址。
(当然,数组的第一个参数的地址也与数组本身的地址相同,所以如果你int (*)[2]
,你会看到相同的地址值(但类型会不同 - printf("%u", &a);
的类型为&a
)。)
接下来,int (*)[3][2]
。您只能取消引用指针,因此*a
首先降级为指针(a
),然后取消引用(&a[0]
)。结果是*&a[0]
,a[0]
的第一个元素。 a
的类型为a[0]
,即2个整数的数组。同样如上所述,数组无法传递,因此当您将其传递给int [2]
时,会降级为指向其第一个参数的指针,即printf
,其类型为&a[0][0]
,指向int的指针。那是你看到的第二个地址。同样,它将与上面的地址相同,因为int *
的地址与其第一个元素a[0]
的地址相同(但类型不同)。
最后,您有a[0][0]
。如上所述,**a
为*a
,降级,然后解除引用。请记住,a
具有类型*a
,即数组类型。与int [2]
一样,当您取消引用它时,它会在解除引用之前将其隐式地降级为指针。因此,a
为**a
,降级,解除引用,降级并再次取消引用。有关正在发生的事情的更明确的描述是a
。最终结果为*&(*&a[0])[0]
,其类型为a[0][0]
。