在这个程序中,我提到的所有三个地址都引用了数组的第一个元素,但为什么在我取消引用它时我不能得到数组的第一个元素的值?
int main()
{
int a[5] = {1,2,3,4,5};
printf("address a = %d\n",a);
printf("address of a[0] = %d\n",&a[0]);
printf("address of first element = %d\n",&a);
printf("value of first element of the array a =%d\n",*(a));
printf("first element =%d\n",*(&a[0]));
printf("a[0] = %d\n",*(&a));//this print statement again prints the address of a[0]
return 0;
}
我获取前3个打印语句的数组a
的第一个元素的地址,当我取消引用所有3个我获取的值仅用于第四个和第五个打印语句而不是第六个打印语句(这附有评论)。
答案 0 :(得分:5)
要记住的事情:
因此,当数组名称为a时,打印a将为您提供a[0]
的地址(也是数组的地址),即您将获得&a[0]
的值(与a
)相同,&a
为相同
现在,您知道a
和&a[0]
引用第一个元素,您可以通过3种方式取消引用第一个元素: -
*a
*(&a[0])
a[0]
- 请注意,在内部,这会转换为:*(a+0)
要记住的事情:
2.向指针添加整数会将指针指向下一个元素
这里,&a
指向整个数组的地址。虽然&a
的值与&a[0]
和a
相同,但它是指向数组的指针,而不是指向第一个元素的指针。
因此,如果您向&a
添加1,即&a + 1
,那么您将超越此数组。
SImilarly,因为&a[0]
和a
是指向第一个元素的指针,向它们添加1将为您提供数组的下一个元素(如果数组中定义了多个项目) 。即(a+1)
和&a[0] + 1
指向第一个元素的下一个元素。现在,要取消引用它们,您可以使用:
*(a+1)
*(&a[0] +1)
a[1]
- 请注意,在内部,这会转换为:*(a+1)
添加更多信息以消除以下疑问:
如果,如这个答案所述,数组的名称是其第一个元素的地址,则& a将是第一个元素的地址。
这个疑问的答案是否和是。
好的,足够的巧克力来解释。
这里,框表示巧克力的数组。因此,我们每人有5盒5个巧克力。声明就是:
将其翻译为C,假设a
是一个包含5个数字的数组。
- 如果我要求您告诉我第一个方框的位置,那么,您将其称为&a
。如果我要求您告诉我第二个方框的位置,那么,您将其称为&a +1
。
&a[0]
或(a+0)
或a
。 &a[1]
或(a+1)
或a+1
。 注意:在(a+1)
中,由于a
是数组的名称,因此它是第一个元素的地址,它是一个整数。因此,将a
增加1意味着第二个元素的地址。(&a+1)
*(&a+1)
或*((&a+1) + 0)
(*(&a+1))+2
答案 1 :(得分:0)
要回答您的问题,根据定义,运算符*
和&
会被取消。获取变量的地址然后解除引用会返回变量。这是一个数组a
。在大多数情况下,数组“衰减”到指针,所以你再看到的是第一个元素的地址。
答案 2 :(得分:0)
C标准指定将类型为“ type ”的表达式转换为“指向 type ”的类型,并指向数组的初始元素,除非表达式是&
的操作数(或其他三个例外情况,如下所述,但与此问题无关)。以下是这适用于您的示例:
a
是一个int数组。它被转换为指向int的指针。该值是a
的初始元素的地址。&a[0]
中,首先处理a[0]
。 a
再次转换为指向int的指针。然后应用下标运算符,它为数组的初始元素生成左值。最后,&
获取此左值的地址,因此该值是a
的初始元素的地址。&a
中,a
是&
的操作数,因此a
不转换为指向int的指针。它仍然是一个数组,&a
取其地址。结果的类型是“指向int数组的指针”,它的值是数组的地址,它等于初始元素的地址。完整性:C标准中的相关规则是6.3.2.1第3段。例外情况是:
&
。sizeof
。_Alignof
。最后一个意味着在char s[] = "abc";
中,"abc"
未转换为指向初始元素的指针;它仍然是一个数组,用于初始化s。
答案 3 :(得分:-1)
a
是指针,a[0]
是*(a+0)
。因此,当您编写*(&a)
时,您不会取消引用它。