#include<stdio.h>
main()
{ int x[3][5]={{1,2,10,4,5},{6,7,1,9,10},{11,12,13,14,15}};
printf("%d\n",x);
printf("%d\n",*x); }
这里首先printf会打印第一个元素的地址。 那么为什么不第二个printf打印地址x的值,即第一个值。 要打印我需要写入** x的值。请解释C中指针的含糊性?
#include<stdio.h>
main()
{ int x[3][5]={{1,2,10,4,5},{6,7,1,9,10},{11,12,13,14,15}};
printf("%d\n",x);
printf("%d\n",*x); }
这里首先printf会打印第一个元素的地址。 那么为什么不第二个printf打印地址x的值,即第一个值。 要打印我需要写入** x的值。请解释C中指针的含糊性?
对于指针来说,x[0]
与*x
相同。由此得出*x[0]
与**x
相同。
在*x[0]
:
x
为int[3][5]
,在表达式中使用时,其被转换到int(*)[5]
。所以x [0]是类型int[5]
(第一个5元素“行”)的左值,它被再次转换为int*
,并取消引用其第一个元素。
*x
沿着相同的路线进行评价,除了第一个非关联化用星号(相对于分度),以及没有第二解引用完成的,因此我们最终int[5]
类型的左值,它被传递给printf
作为其第一个元素的指针。
想象一个2-d数组作为指针数组,数组中的每个元素都指向另一个数组中的第一个元素。当您取消引用x
时,将得到x指向的内存位置中的值...指向int
的第一个int
的指针。当您取消引用该指针时,您将获得第一个元素。
当用作函数的参数时,数组衰减成指向数组第一个元素的指针。也就是说,x
衰减到的对象类型是指向第一个子数组的指针,它是指向int
或基本上int (*)[5]
的数组的指针。当您拨打printf("%d\n",*x)
时,您不会将整数值输入到printf
,而是指向第一个子阵列x
的指针。由于该子阵列也将衰减到指向第一个子阵列元素的指针,因此您可以执行**x
来取消引用该后续指针并获取第一个子阵列x
的第一个元素。这与*x[0]
实际上是相同的,按运算符优先级将索引到x
的第一个子数组中,然后将指针解引用到第一个子数组将衰减到的第一个子数组的元素。
由于*x
的类型是“指向5个数组的指针”。所以,你需要一个更提领来获得的第一个元素
PS:
#include <typeinfo>
#include <iostream>
typedef int arr[5]; // can't compile if put arr[4] here
void foo(arr& x)
{
}
int main()
{
int x[3][5]={{1,2,10,4,5},{6,7,1,9,10},{11,12,13,14,15}};
std::cout << typeid(*x).name() << std::endl;// output: int [5]
foo(x[0]);
return 0;
}
'* x'的类型是“指向'int'”('int *')的指针。它是'x'本身,在数组类型衰减到表达式中的指针之后,该表达式的类型为“指向5个int的数组的指针”。 –
Erm,'* x'的类型是“5个整数”,所以我稍微错了。在大多数情况下,这种衰减会输入“指向int的指针”。在任何解释中,它肯定没有类型“指向5个整数的数组”。 –
是的,我改变了我的原始信息并添加了一些“证明”。 – qehgt
你肯定第一个printf将打印地址,而不是价值? –