C語言中自增自減的編譯原理

2021-09-28 16:53:01 字數 1677 閱讀 8116

i++ 與 ++i 的主要區別有兩個:

1、 i++ 返回原來的值,++i 返回加1後的值。

2、 i++ 不能作為左值,而++i 可以。

毫無疑問大家都知道第一點(不清楚的看下下面的實現**就了然了),我們重點說下第二點。

首先解釋下什麼是左值(以下兩段引用自中文維基百科『右值引用』詞條)。

左值是對應記憶體中有確定儲存位址的物件的表示式的值,而右值是所有不是左值的表示式的值。
一般來說,左值是可以放到賦值符號左邊的變數。但

能否被賦值不是區分左值與右值的依據。比如,c++的const左值是不可賦值的;而作為臨時物件的右值可能允許被賦值。左值與右值的根本區別在於是否允許取位址&運算子獲得對應的記憶體位址。
比如,

int i = 0;

int *p1 = &(++i); //正確

int *p2 = &(i++); //錯誤

++i = 1; //正確

i++ = 5; //錯誤

那麼為什麼『i++ 不能作為左值,而++i 可以』?

看它們各自的實現就一目了然了:

// 字首形式:

int& int::operator++() //這裡返回的是乙個引用形式,就是說函式返回值也可以作為乙個左值使用

//字尾形式:

const int int::operator++(int) //函式返回值是乙個非左值型的,與字首形式的差別所在。

如上所示,i++ 最後返回的是乙個臨時變數,而臨時變數是右值

c語言對於解決這個問題的解決方案可以歸納為乙個很簡單的規則:每乙個符號應該包含盡可能多的字元。也就是說,編譯器將程式分解成符號的方法是:從左到右乙個乙個字元的讀入,字元乙個字元地讀入,如果該字元可能組成乙個符號,那麼再讀入下乙個字元,判斷已經讀入的兩個字元組成的字串是否可能是乙個符號的組成部分;如果可能,繼續讀入下乙個字元,重複上述判斷,直到讀入的字元組成的字串已不再可能組成乙個有意義的符號。這個處理策略有時被稱為「貪心法」,或者,更口語化一點,稱為「大嘴法」,kernighan與ritchie對這個方法的表述如下,「如果(編譯器的)輸入流截止至某個字元之前都已經被分解為乙個個符號,那麼下乙個號將包括從該字元之後可能組成乙個符號的最長字串。」

​ ---《c陷阱和缺陷》 第八頁

自增(字尾):

turbo c中,先統一取值後依次自增;

vs中,從左向右依次取值自增;

int a,i=5; 

a=i+++i+++i++;

//按照貪心演算法,結果為(i++)+(i++)+(i++)

//turbo c中:a=5+5+55=15,i=8

//vs中:a=5+6+7=18,i=8

int a,i=5; 

a=++i+++i+++i;

//編譯錯誤

//編譯器編譯後,((++i)++)+(i++)+i

++i返回的是乙個引用形式,無法在對(++i)在進行自增。

C語言自增自減

i,i 使用i之前,先使i的值加 減 1。i i 使用i之後,再使i的值加 減 1。其中 i和i 的作用相當於i i 1。但是 i和i 不同之處在於 i是先執行i i 1後,再使用i的值 而i 是先使用i的值後,再執行i i 1。例如 i 6a i i的值先變成7,再賦值給a,a的值才為7 b i ...

C語言中printf中自增自減問題

1 printf函式對於括號內的表示式是從右向左執行,如 printf d,d i i 先執行 i,再執行i 從左向右輸出。2 對於 i和i i是先自加,再呼叫 i 是先呼叫,再自加。1 include void main 結果 22,22 21,22 21,20 22,20 分析 printf語句...

C語言 自增( ) 自減( )運算

1.作用 自增運算使單個變數的值增 自減運算使單個變數的值減 2.用法與運算規則 自增 自減運算子都有兩種用法 1 前置運算 運算子放在變數之前 變數 變數 先使變數的值增 或減 然後再以變化後的值參與其它運算,即先增減 後運算。2 後置運算 運算子放在變數之後 變數 變數 變數先參與其它運算,然後...