簡體   English   中英

理解對C中包含'++'和' - >'運算符的表達式的評估

[英]Understanding evaluation of expressions containing '++' and '->' operators in C

考慮這個例子:

struct {
    int num;
} s, *ps;

s.num = 0;
ps = &s;
++ps->num;

printf("%d", s.num); /* Prints 1 */

它打印1
所以我理解這是因為根據運算符優先級, ->高於++ ,所以首先獲取值ps->num (即0),然后++運算符對其進行操作,因此它將其遞增為1。

struct {
    int num;
} s, *ps;

s.num = 0;
ps = &s;
ps++->num;

printf("%d", s.num); /* Prints 0 */

在這個例子中,我得到0 ,我不明白為什么; 對於這個例子,第一個例子的解釋應該是相同的。 似乎這個表達式的評估如下:
首先,運算符++運行,並且它在ps運行,因此它將它遞增到下一個struct 只有這樣->運行並且它什么都不做,因為它只是獲取下一個structnum字段struct做任何事情。
但它與運算符的優先級相矛盾,后者表示->具有比++更高的優先級。

有人可以解釋這種行為嗎?

編輯
在閱讀了兩個引用C ++優先級表的答案后,表示前綴++ / --運算符的優先級低於-> ,我做了一些谷歌搜索,並提出了這個鏈接 ,表明此規則也適用於C本身。 它恰好完全解釋了這種行為,但我必須補充一點,這個鏈接中的表與我自己的K&R ANSI C副本中的表相矛盾。所以如果你有關於哪個源是正確的建議我想知道。

謝謝。

后增量( ps++ )和預增量( ++ps )在C中具有不同的關聯性。前者從左到右關聯,而后者從右到左關聯。 檢查頁面(雖然這是針對C ++的,因此優先級可能會產生誤導)。

在上一個示例中,您將指針更改為超過&s結尾的指針。 您沒有更改指針的值。 如果需要增加num ,則需要將++綁定到num

詳細說明:

 ps++->num;

看到這個表達式的(假設的)編譯器可以將ps對象推送到堆棧,然后是++運算符, ->運算符,最后是object - num 在評估時,編譯器應該從哪里開始? 它查看可用的運算符,即++-> 它選擇ps++還是ps 這里是優先規則:因為->的優先級高於++ ,所以需要->num作為一個操作數進行處理,將ps作為另一個操作數進行處理。 因此,正確觀察時,表達式的值變為ps->num即0。 評估后ps會發生什么? 請記住,堆棧上還有另一個操作員? 因此,編譯器將此應用於ps ,它現在指向一個元素過去&s

腳注:

ANSI / ISO C標准不使用運算符優先級語法。 相反,它使用所謂的完全因子語法。 這通常涉及嚴格的語法定義,其中點綴有許多非終端,如“primary-expression”和“shift-expression”等。 這很難理解,但對語言設計者或編譯器供應商來說更容易理解。 而且,這樣的語法能夠容易地編碼優先級。 但是,任何完全分解的語法都與運算符優先級語法兼容,這是大多數書籍(和網站)所做的(有時也會搞亂)。

即使++具有更高的優先級,這也不會改變值 - >操作,因為它是后增量。 請參閱此代碼,其中還包含此行為的另一個示例:

int b = 5;
int a = b++ * 3;
b = 5;
int c = (b++) * 3;

printf("%i, %i, %i\n", a, b, c); // Prints 15, 6, 15

struct {
  int num;
} s, *ps;

s.num = 35;
ps = &s;
printf("%p\n", ps); // Prints the pointer
printf("%i\n", ps++->num); // Prints 35
printf("%p\n", ps); // Prints the increased pointer

printf("%d\n", s.num); /* Prints 35 */

b = ++ a; 相當於:

a += 1;
b = a;

b = a ++; 相當於:

b = a;
a += 1;

所以很明顯為什么你沒有得到你想要的結果。 你描述的東西相當於(++ ps) - > num。

“優先權”基本上是衍生財產; 它來自解析規則。 ++ ps-> num被解析為++(ps-> num)/ *(),用於澄清解析規則* /而ps ++ - > num只能解析為(ps ++) - > num。

我想這是因為它們具有不同的優先級,並且在同一組中,它們具有特定的關聯性(例如,評估順序)

點擊這里 后綴運算符與指針解析具有相同的優先級,但前綴運算符的優先級較低。

ps ++ - > num將指針ps遞增1,然后讀取其中的數據。 因為ps就在堆棧上的s之后,我相信指針很可能指向自己,雖然我不確定,但並不重要。 基本上初始程序正在做++(ps-> num)但沒有括號。 要實現同樣的目的,但在訪問數據之后,您必須執行(ps-> num)++,或者不使用括號:ps-> num ++。

因為ps只是一個指針,即使你改變它的值,s仍然保持不變。

優先級用於解決模糊解析。 ++ps->num可以解析為((++ps)->num)(++(ps->num)) ; ++()->的相對優先級確定后者是正確的解析。

對於ps++->num ,只有一個有效的解析: ((ps++)->num) ,因此運算符的優先級無關緊要。

在這里您可以看到++作為前綴的優先級低於 - >,但作為后綴,它具有與 - >相同的優先級,並且從左到右進行評估,因此首先完成ps ++,然后是 - >。

編輯:這是針對C ++,而不是C.所以我的答案是不正確的。

暫無
暫無

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

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