C語言中的自增自減運算符詳解,printf等函數的應用,及其源碼等
- 前言
-
- 作用
- 基礎的介紹
- 一些應用中的坑
-
- 連加時的加号左結合性
- 條件運算符中的短路規則
- 負号的右結合性
- printf的出棧入棧與壓參列印方向
- 源碼(解釋一下左值的問題)
前言
本人大一新生,接觸C語言才幾周,是以有錯的地方,還請大佬們評論區給我說一下或者私聊均可。這篇部落格是我被要求做自增自減PPT的産物,原本以為很簡單,逛完論壇才發現坑好多。有些不适合課上說的,都放到這了。
作用
這是最簡單的了,可分為前置與後置。
前置:
#include<stdio.h>
int main()
{
int i(1);
++i;
printf("%d",i);
return 0;
}
或
#include<stdio.h>
int main()
{
int i(1);
--i;
printf(“%d”,i);
return 0;
}
後置:
#include<stdio.h>
int main()
{
int i(1);
i++;
printf(“%d”,i);
return 0;
}
或
#include<stdio.h>
int main()
{
int i(1);
i--;
printf(“%d”,i);
return 0;
}
答案就不必說了,懂的都懂,前置與後置的差別是:前置先将變量自身加一,然後再帶入計算表達式;後置是先帶入計算表達式,然後再将變量的值加一。
接下來以i++與++i為介紹對象,減号與之同理。
基礎的介紹
1.它是單目運算符,且具有右結合性,是以隻針對單個變量,無法針對表達式或常量。對于k=++i++(即k=++(i++));或6++這種類型的是錯誤的。
2.++i可以作為左值,但是i++不行(這個後面說源碼時會介紹我自己了解的原因)
3.讀取規則按照貪心法,即一個字元下盡可能多的結合其他字元。這裡為了程式的可讀性與後期維護,還是用括号分開吧,空格也可以起到同樣的作用。
比如:對于
#include<stdio.h>
int main()
{
int a,i(1);
a=++i + ++i + ++i;
printf(“%d”,a);
return 0;
}
輸出結果是a=10;i=4;(為什麼a=10,後面會解釋)
如果不加空格或括号的話,這個表達式會被系統依據貪心法認為是++(i++)+(i++)+i;就直接報錯了。
一些應用中的坑
連加時的加号左結合性
對于剛才提到的a=++i + ++i + ++i,這兩個加号的優先級一樣,是以取決于其結合性。
是以系統之前讀出來的不是a=(++i)+(++i)+(++i),而是a=((++i)+(++i))+(++i)。
翻譯過來是這樣
#include<stdio.h>
int main()
{
int i(1),a;
i=i+1;
i=i+1;
a=i+i;
i=i+1;
a=a+i;
printf(“%d”,a);
return 0;
}
是以a=(3+3)+4=10;
條件運算符中的短路規則
這個主要是if的條件中如果用了&&或||,且後面的條件包括自增自減,可能會被短路掉,不作處理。
例如:
#include<stdio.h>
int main()
{
int i(1);
if(1!=0||i++)
printf(“%d”,i);
return 0;
}
和
#include<stdio.h>
int main()
{
int i(1);
if(1==0&&i++)
printf(“%d”,i);
return 0;
}
由于都被短路掉了,是以輸出的i值都是1。
負号的右結合性
由于優先級相同是以取決于“-”的右結合性,遵循從右到左的執行順序。
這個比較簡單是以不舉例了。
printf的出棧入棧與壓參列印方向
printf函數是先從後往前周遊所有元素并計算出每個元素對應的變量的值,然後将相應的臨時變量或實參入棧,最後出棧列印。是以printf的最終列印是最後一步。i與前置最後入棧的都是i的實參,是以列印的是i的終值。而後置都是讀取的相應的臨時變量。
例如
#include<stdio.h>
int main()
{
int i(1);
printf(“%d %d %d %d”,i++,++i,++i,i++);
return 0;
}
對應的是4,5,5,1;
翻譯一下是:
取i的值為一臨時變量(q);
i=i+1;
傳回i值為2;
i=i+1;
傳回i值為3;
以實參i為其傳回值;
i=i+1;
傳回i值為4;
以實參i為其傳回值;
取i的值為一臨時變量(w);
i=i+1;
傳回i值為5;
将“臨時變量q,實參i,實參i,臨時變量w”依次壓入棧中,最後出棧列印。
源碼(解釋一下左值的問題)
int& int::operator++()
{
*this += 1;
return *this;
}
const int int::operator++(int)
{
int oldValue = *this;
++(*this);
return oldValue;
}
(來自“C語言中自增自減的編譯原理”)
很明顯的看到i++傳回的是臨時變量自然沒有固定的記憶體位址,就做不了左值,而++i;改變的是其自身的實參是以可以用來作為左值。