简体   繁体   English

C中的数组增量运算符

[英]Array increment operator in C

I don't understand the results of following code: 我不明白以下代码的结果:

#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;
}

Why does the second printf function produce following error? 为什么第二个printf函数会产生以下错误?

error: lvalue required as increment operand

Part-1: 第1部分:

Array names are constant (not modifiable lvalue), your can add value to array name but can't modify it. 数组名称是常量(不可修改的左值),您可以向数组名称添加值但不能修改它。

Expression a + 2 doesn't modify a itself but when you do a++ that is equivalent to a = a + 1 try to modify array name --lvalue error. 表达a + 2不修改a本身,而是当你做a++等同于a = a + 1试图修改数组名--lvalue错误。 The expression a++ in second printf is wrong - an example of semantic phase error. 第二个printf中的表达式a++是错误的 - 语义相位错误的一个例子。 read following language standards: 阅读以下语言标准:

6.3.2.1 Lvalues, arrays, and function designators 6.3.2.1左值,数组和函数指示符

724 A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type. 724可修改的左值是一个左值,它没有数组类型,没有不完整的类型,没有const限定类型,如果是结构或联合,则没有任何成员(包括,递归,任何具有const限定类型的所有包含聚合或联合的成员或元素。

729 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type “array of type” is converted to an expression with type “pointer to type” that points to the initial element of the array object and is not an lvalue . 729除非它是sizeof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则将类型为“array of type”的表达式转换为类型为“指向类型的指针”的表达式指向数组对象的初始元素,而不是左值

Part-2: 第2部分:

Note array names in most expressions decays in address of first element (read some exceptions where array name not decaying into a pointer to first element? ably answered by @H 2 CO 3 ). 注意大多数表达式中的数组名称在第一个元素的地址中衰减(读取一些异常,其中数组名称不会衰减为指向第一个元素的指针? @H 2 CO 3可以很好地回答)。

When you do a + 2 its result is address of third element (or address of element at index 2 ) So a + 2 is same as &a[2] It is address not value at index. 当你做a + 2它的结果是第三个元素的地址(或索引2处元素的地址)所以a + 2&a[2]相同&a[2]它是索引处的地址而不是值。

To print address use %p instead of %d and typecast address into void* as follows: 要打印地址,请将%p而不是%d和类型转换地址用于void* ,如下所示:

printf("address (a + 2) = %p , &a[2] = %p", (void*)(a + 2), (void*)(&a[2]));

To print value you need defence operator * as follows: 要打印值,您需要防御操作员* ,如下所示:

printf("address *(a + 2) = %d , a[2] = %d", *(a + 2), a[2]);   

Part-3: 部分3:

suppose a is stored at location 2010, Is the output of first printf function 2012? 假设a存储在2010年的位置,是第一个printf函数2012的输出吗?

No, pointer arithmetic is different then integer arithmetic. 不,指针运算与整数运算不同。 As we know array name decays into address of first element's address in most expressions So when you do a + 2 the value is address of third element that is at index 2 . 我们知道数组名称在大多数表达式中衰减为第一个元素地址的地址所以当你执行a + 2该值是索引2处的第三个元素的地址。 So suppose if int size in your system is 4 bytes then a + 2 stat pointing to location 2018 according to your assumption that a address value is 2010. 因此,假设如果你的系统INT大小为4个字节,然后a + 2 ,根据你的假设,统计指向位置2018 a地址值2010。

To understand read 10.2 Pointers and Arrays; 要理解10.2指针和数组; Pointer Arithmetic and Pointer Arithmetic . 指针算术指针算法

int a[4]={1,3,5,6}; 

printf("%d\n",a++); // you should not modify array name

 illegal in c

Assume pa is integer pointer 假设pa是整数指针

A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal.

I think the first output will be depedent on how the integer type is represented in your computer. 我认为第一个输出将依赖于计算机中整数类型的表示方式。 If a single integer occupies 4-bytes in memory, the output should be 2018, ie 2010+2*4. 如果单个整数在内存中占用4个字节,则输出应为2018,即2010 + 2 * 4。 The second printf can cause a compilation error. 第二个printf可能导致编译错误。

First this program invokes undefined behavior and I am little discouraged that with so many answers not one of them mentions this. 首先,这个程序会调用未定义的行为 ,我很少气馁,因为有这么多答案,其中没有一个提到这个。 In both your printf calls your argument is a pointer yet your are specifying the format as %d which expects and int it should be %p . 在你的两个printf调用中,你的参数是一个指针 ,你的格式为%d ,期望和int 应该是%p The C99 draft standard in section 7.19.6.1 The fprintf function which printf 's section refers back to for the format string paragraph 9 says: 7.19.6.1节中的C99草案标准 printf的部分引用的fprintf函数返回格式字符串第9段说:

If a conversion specification is invalid, the behavior is undefined.[...] 如果转换规范无效,则行为未定义。[...]

Back to your question, the a++ expression produces an error because postfix increment requires that it's operand is a modifiable lvalue , the draft standard in section 6.5.2.4 Postfix increment and decrement operators paragraph 1 says( emphasis mine ): 回到你的问题, a++表达式产生一个错误,因为后缀增量要求它的操作数是一个可修改的左值6.5.2.4节中的草案标准增量和减量运算符1段说( 强调我的 ):

The operand of the postfix increment or decrement operator shall have qualified or unqualified real or pointer type and shall be a modifiable lvalue . 后缀增量或减量运算符的操作数应具有限定或不合格的实数或指针类型,并且应为可修改的左值

we can see from setion 6.3.2.1 values, arrays, and function designators paragraph 1 says: 我们可以从第6.3.2.1看到的值,数组和函数指示符1段说:

[...]A modifiable lvalue is an lvalue that does not have array type[...] [...]可修改的左值是一个没有数组类型的左值[...]

Array memory addresses remain constant, so you cannot change it. 数组内存地址保持不变,因此您无法更改它。 That's what you are doing in a++ statement. 这就是你在++语句中所做的。 So compiler will throw error. 所以编译器会抛出错误。

a不是int类型的变量,它是指向整数的指针,因此要打印它,首先需要取消引用它

printf("%d\n", *(a + 2));

The name of array is a constant pointer and so it will always point to the 0th element of that array. 数组的名称是一个常量指针,因此它总是指向该数组的第0个元素。 It is not a variable so nor can we assign some other address to it neither can we move it by incrementing or decrementing. 它不是一个变量,所以也不能为它分配一些其他地址,也不能通过递增或递减来移动它。 Hence 于是

a = &var;  /*Illegal*/
a++;       /*Illegal*/
a = a-1;   /*Illegal*/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM