C中的数组增量运算符

use*_*458 9 c pointers post-increment

我不明白以下代码的结果:

#include <stdio.h>
#include <conio.h>
int main()
{
   int a[4]={1, 3, 5, 6};
   //suppose a is stored at location 2010
   printf("%d\n", a + 2);
   printf("%d", a++);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么第二个printf函数会产生以下错误?

error: lvalue required as increment operand

Gri*_*han 14

第1部分:

数组名称是常量(不可修改的左值),您可以向数组名称添加值但不能修改它.

表达式a + 2不会自行修改,a但是当您这样做时a++,相当于a = a + 1尝试修改数组名称--lvalue错误.a++第二个printf中的表达式是错误的 - 语义相位错误的一个例子.阅读以下语言标准:

6.3.2.1左值,数组和函数指示符

724可修改的左值是一个左值,它没有数组类型,没有不完整的类型,没有const限定类型,如果是结构或联合,则没有任何成员(包括,递归,任何具有const限定类型的所有包含聚合或联合的成员或元素.

729 除非它是sizeof运算符或一元运算&符的操作数,或者是用于初始化数组的字符串文字,否则将类型为"array of 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]));
Run Code Online (Sandbox Code Playgroud)

要打印值,您需要防御操作符*,如下所示:

printf("address *(a + 2) = %d , a[2] = %d", *(a + 2), a[2]);   
Run Code Online (Sandbox Code Playgroud)

部分3:

假设a存储在2010年的位置,是第一个printf函数2012的输出吗?

不,指针运算与整数运算不同.我们知道数组名称在大多数表达式中衰减为第一个元素地址的地址所以当你这样做时a + 2,值是索引处的第三个元素的地址2.因此,假设系统中的int size是4个字节,那么a + 2根据您的a地址值为2010的假设,stat指向2018位置.

要理解10.2指针和数组; 指针算术指针算法.

  • 鉴于`a`是数组对象的名称,`a ++`*没有意义*. (2认同)