簡體   English   中英

C中的數組增量運算符

[英]Array increment operator in C

我不明白以下代碼的結果:

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

為什么第二個printf函數會產生以下錯誤?

error: lvalue required as increment operand

第1部分:

數組名稱是常量(不可修改的左值),您可以向數組名稱添加值但不能修改它。

表達a + 2不修改a本身,而是當你做a++等同於a = a + 1試圖修改數組名--lvalue錯誤。 第二個printf中的表達式a++是錯誤的 - 語義相位錯誤的一個例子。 閱讀以下語言標准:

6.3.2.1左值,數組和函數指示符

724可修改的左值是一個左值,它沒有數組類型,沒有不完整的類型,沒有const限定類型,如果是結構或聯合,則沒有任何成員(包括,遞歸,任何具有const限定類型的所有包含聚合或聯合的成員或元素。

729除非它是sizeof運算符或一元&運算符的操作數,或者是用於初始化數組的字符串文字,否則將類型為“array of type”的表達式轉換為類型為“指向類型的指針”的表達式指向數組對象的初始元素,而不是左值

第2部分:

注意大多數表達式中的數組名稱在第一個元素的地址中衰減(讀取一些異常,其中數組名稱不會衰減為指向第一個元素的指針? @H 2 CO 3可以很好地回答)。

當你做a + 2它的結果是第三個元素的地址(或索引2處元素的地址)所以a + 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該值是索引2處的第三個元素的地址。 因此,假設如果你的系統INT大小為4個字節,然后a + 2 ,根據你的假設,統計指向位置2018 a地址值2010。

要理解10.2指針和數組; 指針算術指針算法

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

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

 illegal in c

假設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.

我認為第一個輸出將依賴於計算機中整數類型的表示方式。 如果單個整數在內存中占用4個字節,則輸出應為2018,即2010 + 2 * 4。 第二個printf可能導致編譯錯誤。

首先,這個程序會調用未定義的行為 ,我很少氣餒,因為有這么多答案,其中沒有一個提到這個。 在你的兩個printf調用中,你的參數是一個指針 ,你的格式為%d ,期望和int 應該是%p 7.19.6.1節中的C99草案標准 printf的部分引用的fprintf函數返回格式字符串第9段說:

如果轉換規范無效,則行為未定義。[...]

回到你的問題, a++表達式產生一個錯誤,因為后綴增量要求它的操作數是一個可修改的左值6.5.2.4節中的草案標准增量和減量運算符1段說( 強調我的 ):

后綴增量或減量運算符的操作數應具有限定或不合格的實數或指針類型,並且應為可修改的左值

我們可以從第6.3.2.1看到的值,數組和函數指示符1段說:

[...]可修改的左值是一個沒有數組類型的左值[...]

數組內存地址保持不變,因此您無法更改它。 這就是你在++語句中所做的。 所以編譯器會拋出錯誤。

a不是int類型的變量,它是指向整數的指針,因此要打印它,首先需要取消引用它

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

數組的名稱是一個常量指針,因此它總是指向該數組的第0個元素。 它不是一個變量,所以也不能為它分配一些其他地址,也不能通過遞增或遞減來移動它。 於是

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM