我在C中编写了以下代码:
#include<stdio.h>
int main()
{
int a[10][10]={1};
//------------------------
printf("%d\n",&a);
printf("%d\n",a);
printf("%d\n",*a);
//-------------------------
printf("%d",**a);
return 0;
}
使用上面3个printf语句,我得到了相同的值。在我的机器上它是2686384.但是最后一个声明我得到了1。
这不是出问题吗?这些陈述意味着:
a
的地址是2686384 a
中存储的值为2686384 a
指向的变量地址(即2686384)存储的值为2686384. 这意味着a
必须像一个指向自身的变量......
那么为什么*(*a)
1的输出?为什么不将其评估为*(*a)=*(2686384)=2686384
?
答案 0 :(得分:2)
#include<stdio.h>
int main()
{
// a[row][col]
int a[2][2]={ {9, 2}, {3, 4} };
// in C, multidimensional arrays are really one dimensional, but
// syntax alows us to access it as a two dimensional (like here).
//------------------------
printf("&a = %d\n",&a);
printf("a = %d\n",a);
printf("*a = %d\n",*a);
//-------------------------
// Thing to have in mind here, that may be confusing is:
// since we can access array values through 2 dimensions,
// we need 2 stars(asterisk), right? Right.
// So as a consistency in this aproach,
// even if we are asking for first value,
// we have to use 2 dimensional (we have a 2D array)
// access syntax - 2 stars.
printf("**a = %d\n", **a ); // this says a[0][0] or *(*(a+0)+0)
printf("**(a+1) = %d\n", **(a+1) ); // a[1][0] or *(*(a+1)+0)
printf("*(*(a+1)+1) = %d\n", *(*(a+1)+1) ); // a[1][1] or *(*(a+1)+1)
// a[1] gives us the value on that position,
// since that value is pointer, &a[i] returns a pointer value
printf("&a[1] = %d\n", &a[1]);
// When we add int to a pointer (eg. a+1),
// really we are adding the lenth of a type
// to which pointer is directing - here we go to the next element in an array.
// In C, you can manipulate array variables practically like pointers.
// Example: littleFunction(int [] arr) accepts pointers to int, and it works vice versa,
// littleFunction(int* arr) accepts array of int.
int b = 8;
printf("b = %d\n", *&b);
return 0;
}
答案 1 :(得分:1)
包含数组名称的表达式可以衰减到指向数组第一个元素的指针。因此即使a
具有int[10][10]
类型,它也可以衰减为int(*)[10]
。
现在,这种衰变发生在表达式*a
中。因此表达式具有类型int[10]
。重复相同的逻辑,这再次衰减到int*
,因此**a
是int
,而且它是数组a
的第一个元素的第一个元素,即1
。
其他三个打印语句分别打印出数组的第一个元素的数组的地址,以及数组的第一个元素的第一个元素(当然所有相同的地址,只是不同的类型)。
答案 2 :(得分:1)
首先,关于数组的一个词......
除非它是sizeof
,_Alignof
或一元&
运算符的操作数0,或者是用于在声明中初始化另一个数组的字符串文字, >“{元素数组T
”类型的>表达式将被转换(“衰减”)为“指向T
的指针”类型的表达式,表达式的值将是数组中第一个元素的地址。
表达式&a
具有类型“指向10个元素数组int
”或int (*)[10][10]
的10元素数组的指针。表达式a
具有“10元素数组int
的10元素数组”,按照上面的规则衰减为“指向int
的10元素数组”,或者int (*)[10]
。最后,表达式*a
(相当于a[0]
)的类型为“10个元素的int
数组”,再次按照上面的规则衰减到“int
的指针}}”。
所有三个表达式都具有相同的值,因为数组的地址和第一个元素的地址是相同的:&a[0][0]
== a[0]
== {{ 1}} == *a
== a
。但是,表达式的类型是不同的,这在进行指针运算时很重要。例如,如果我有以下声明:
&a
然后int (*ap0)[10][10] = &a;
int (*ap1)[10] = a;
int *ip = *a;
会提前ap0++
指向ap0
的下一个10x10数组,int
会提前ap1++
指向下一个10元素数组ap1
(或int
)和a[1]
会提前ip++
指向下一个ip
(int
)。
&a[0][1]
相当于**a
,相当于*a[0]
。这是a[0][0]
的第一个元素的值,其类型为a
,值为int
(请注意仅 {{ 1}}被初始化为1
;所有剩余的元素都被初始化为a[0][0]
)。
请注意,您应该使用1
打印出指针值:
0
答案 3 :(得分:0)
首先,如果要打印指针值,请使用%p
- 如果您使用的是64位机器,则int几乎肯定小于指针。
**a
双重解引用实际上是int**
的内容,因此您最终会得到第一个子数组的第一个元素:1。
答案 4 :(得分:0)
如果您将a
定义为T a[10]
(其中T
是某个typedef),那么简单的简单a
表示数组开头的地址,与&a[0]
相同。它们都有T*
类型。
&a
也是数组开头的地址,但它的类型为T**
。
在存在多维数组的情况下,事情变得更加棘手。要查看正在发生的事情,使用typedef将事情分解为更小的块更容易。所以,你有效地写了
typedef int array10[10];
array10 a[10];
[向读者练习:a
的类型是什么? (它不 int**
)]
**a
正确评估数组int
中的第一个a
。
答案 5 :(得分:0)
来自C99标准
考虑声明
int x[3][5];
这里x是3×5的整数数组;更确切地说,x是一个由三个元素对象组成的数组,每个元素对象是一个由五个整数组成的数组。在表达式x [i]中,它等价于(*((x)+(i))), x首先转换为指向初始数组为5个整数的指针。然后根据x的类型调整i,这在概念上需要将i乘以指针所指向的对象的大小,即五个int对象的数组。添加结果并应用间接以产生五个整数的数组。当在表达式x [i] [j]中使用时,该数组又被转换为指向第一个int的指针,因此x [i] [j]产生一个int。
所以,
初始数组仅为x [0] [0]。
所有x,&amp; x和* x将指向x [0] [0]。
答案 6 :(得分:0)
不,你的代码没有任何问题。只是他们想你的方式......我想的越多,我就越难意识到这是解释,所以在我进入这个之前,请记住以下几点:
printf("%d",array[3]);
时,我正在移动和引用所以一个数组(让我们考虑一下维度)就在内存中的某个地方:
int arr[10] = {1};
//Some where in memory---> 0x80001f23
[1][1][1][1][1][1][1][1][1][1]
所以,如果我说:
*arr; //this gives the value 1
为什么呢?因为它与arr[0]
相同,它给出了地址的值,这是数组的开头。这意味着:
arr; // this is the address of the start of the array
那么这给了我们什么呢?
&arr; //this will give us the address of the array.
//which IS the address of the start of the array
//this is where arrays and pointers really show some difference
所以arr == &arr;
。数组的“作业”是保存数据,数组不会“指向”任何其他内容,因为它拥有自己的数据。期。另一方面,指针的作用是指向其他东西:
int *z; //the pointer holds the address of someone else's values
z = arr; //the pointer holds the address of the array
z != &z; //the pointer's address is a unique value telling us where the pointer resides
//the pointer's value is the address of the array
修改强> 还有一种思考方式:
int b; //this is integer type
&b; //this is the address of the int b, right?
int c[]; //this is the array of ints
&c; //this would be the address of the array, right?
所以这是可以理解的:
*c; //that's the first element in the array
这行代码告诉你什么?如果我尊重c
,那么我得到一个int。这意味着普通c
是一个地址。因为它是数组的开头,所以它是数组的地址,因此:
c == &c;