第1部分:
数组名称是常量(不可修改的左值),您可以为数组名称添加值但不能修改它。
表达式a + 2
不会自行修改a
,但是当您这样做时a++
,相当于a = a + 1
尝试修改数组名称 --lvalue 错误。第二个 printf 中的表达式a++
是错误的 - 语义阶段错误的一个例子。阅读以下语言标准:
724可修改的左值是不具有数组类型、不具有不完整类型、不具有 const 限定类型,并且如果它是结构或联合,则不具有任何成员(包括递归地,任何所有包含的聚合或联合的成员或元素)具有 const 限定类型。
729 除非它是 sizeof 运算符或一元&
运算符的操作数,或者是用于初始化数组的字符串字面量,否则类型为“array of type”的表达式将转换为类型为“pointer to type”的表达式指向数组对象的初始元素,不是左值。
第2部分:
注意大多数表达式中的数组名称在第一个元素的地址中衰减(阅读一些异常,其中数组名称没有衰减为指向第一个元素的指针? @H 2 CO 3巧妙地回答了)。
当你这样做时,a + 2
它的结果是第三个元素的地址(或索引处元素的地址2
)所以a + 2
与&a[2]
它是地址而不是索引处的值相同。
打印地址使用%p
代替%d
并将地址类型转换void*
为如下:
printf("address (a + 2) = %p , &a[2] = %p", (void*)(a + 2), (void*)(&a[2]));
要打印值,您需要防御操作员*
,如下所示:
printf("address *(a + 2) = %d , a[2] = %d", *(a + 2), a[2]);
第 3 部分:
假设 a 存储在位置 2010,第一个 printf 函数的输出是 2012 年吗?
不,指针算术不同于整数算术。正如我们所知,数组名称在大多数表达式中都会衰减为第一个元素的地址,所以当你这样做时a + 2
,值是位于 index 的第三个元素的地址2
。因此,假设您的系统中的 int 大小为 4 个字节,那么根据您的地址值为 2010a + 2
的假设,stat 指向位置 2018 。a
要了解阅读10.2 指针和数组;指针算术和指针算术。