C 理解指针和数组
有人能解释一下数组是如何通过名称引用的,比如在指针和双指针前面加上它的名称,如下面的代码所示:C 理解指针和数组,c,arrays,pointers,C,Arrays,Pointers,有人能解释一下数组是如何通过名称引用的,比如在指针和双指针前面加上它的名称,如下面的代码所示: #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);
#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);
}
#包括
main()
{
INTA[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);
}
第一个
printf("%u\n",a);
打印a
的地址,该地址与第一个元素的地址相同
第二个
printf("%u\n",*a);
取消引用a
,并给出a
第三个呢
printf("%u\n",**a);
取消引用指向a
的第一个“行”的指针,并给出此二维数组中第一个元素的值
当您在编译示例时打开了警告时,编译器已经在抱怨,因此会告诉您所使用的某些类型。将指针作为参数时,应使用格式说明符%p
printf("%p\n",a);
printf("%p\n",*a);
格式说明符%u
用于无符号int
,如果有int
,最好使用说明符%d
printf("%d\n",**a);
a
和*a
都是指针,所以在格式化输出中打印它就像在printf()中一样使用%p
作为格式说明符
否则,编译器将显示警告消息
警告:格式“%x”要求类型为“unsigned int”,但参数2的类型为“int(*)[2]”
警告:格式“%x”要求类型为“unsigned int”,但参数2的类型为“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.
这就像a是地址而不是*a是a的值一样
除非它是大小的
、\u Alignof
或一元的&
运算符的操作数,或者是用于初始化声明中另一个数组的字符串文字,否则“T
的N元素数组”类型的表达式将被转换(“衰减”)为“指向T
的指针”类型的表达式,表达式的值将是数组第一个元素的地址
在第一个printf
调用中,表达式a
的类型为“int的2元素数组的3元素数组”;根据上述规则,表达式将转换为类型“指向int
的2元素数组的指针”(int(*)[2]
),其值与&a[0]
相同
在第二个printf
调用中,表达式*a
的类型为“int的2元素数组”;根据上述规则,表达式将转换为类型“指向int
”(int*
),其值将与&a[0][0]
相同(与&a[0]
相同-数组的第一个元素的地址与数组本身的地址相同)
在第三个
printf
调用中,表达式**a
具有typeint
,其值是存储在a[0][0]
中的任何值(在本例中为15)。对类型的检查是有益的
a
具有类型int[3][2]
,即一个由3个数组和2个int组成的数组。但是,不能在C中分配或传递数组类型。将a
传递给printf
时发生的情况是,它降级为指向其第一个参数的指针,即&a[0]
,该参数具有类型int(*)[2]
,即指向2个整数数组的指针。这就是你看到的地址
(当然,数组的第一个参数的地址也与数组本身的地址相同,因此如果您使用printf(“%u”,&a);
,您将看到相同的地址值(但类型不同--&a
将具有typeint(*)[3][2]
)
接下来,*a
。您只能取消引用指针,因此a
首先降级为指针(&a[0]
),然后取消引用(*&a[0]
)。结果是a[0]
,是a
的第一个元素<代码>一个[0]具有类型int[2]
,即2个int的数组。同样如上所述,数组无法传递,因此当您将其传递给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]
,其类型为int
请更好地解释您的问题。我只看到代码无效(前两个printf
语句)。可能重复的请注意,在案例1和案例2中使用%u
是不正确的。printf(“%u\n”,a/*a)
在前两个案例中应该是printf(“%p\n”,a/*a)
。它应该是printf(“%d\n”**a)代码>在最后一种情况下。请考虑更新答案以添加这一点。对于迂腐,指针应该被转换成<代码>空白>代码>。在指向不同类型的指针大小不同的平台上,这实际上很重要(但这些平台可能是假设的)