tft每日頭條

 > 圖文

 > c語言裝逼的代碼

c語言裝逼的代碼

圖文 更新时间:2025-01-15 15:22:52

c語言裝逼的代碼?C語言是現在大部分流行語言的源起,也是編寫系統軟件的不二之選,C語言的一些細節值得深入探究,我來為大家講解一下關于c語言裝逼的代碼?跟着小編一起來看一看吧!

c語言裝逼的代碼(摳一摳C語言的一些細節)1

c語言裝逼的代碼

C語言是現在大部分流行語言的源起,也是編寫系統軟件的不二之選,C語言的一些細節值得深入探究。

1 關于賦值運算符(普通變量和指針變量的賦值)

先看C語言代碼和對應的彙編代碼

7: int a = 5; 00401048 mov dword ptr [ebp-4],5 8: int* b = &a; 0040104F lea eax,[ebp-4]

int a = 5; 彙編指令是move,表示将5的二進制序列傳送到a所對應的内存空間。

可以理解為int a ← 5,将值5賦給a。

再看指針變量的賦值:

int* b = &a;

彙編指令是lea,是Load effective address的縮寫——取有效地址,也就是取偏移地址。

可以理解為 b → a,b指向a。

用結構體做單鍊表的結點時,這樣理解更容易理解鍊表指針的移動:

struct pNode* p,p2; p = p->next;//p指向p的下一個節點空間 p2 = p2->next->next; //p2指向p2的下一個的下一個節點空間

2 賦值與賦初值在效率上的一點差異

二者的區别在于:為變量賦值是通過賦值表達式在運行期間動态賦值,而為變量賦初值則是在定義變量的同時在編譯時靜态賦值。如對a進行賦值,對b進行賦初值,形式如下。

int a,b=3; a=2;

為變量賦值占用的是運行時間,而為變量賦初值占用的是編譯時間。

從上面的分析得知,變量不是一定要初始化的,也可以先進行定義,再進行賦值,這和初始化的效果是一樣的。但是如果想提高運行效率,就得對變量進行初始化。

3 const的一點細節

編譯器通常不為普通const隻讀變量分配存儲空間,而是将它們保存在符号表中,這使它成為一個編譯期間的值,沒有了存儲與讀内存的操作,使得它的效率也更高。

4 逗号作為運算符和分隔符

逗号在C語言中有時可以作為運算符來連接表達式,有時還可以作為分隔符,起到分隔的作用。那麼,該如何區分逗号是運算符還是分隔符呢?

“,”作為分隔符主要用于以下情況:

(1) 變量聲明時,使用逗号分隔多個變量名。

(2) 函數有多個參數時,用逗号分隔參數。

逗号運算符是C語言提供的一種特殊的運算符,用它可以将兩個表達式連接起來。例如,“1 2,4 5”,稱為逗号表達式,也稱為“順序求值運算符”。它的表達式一般形式為“表達式1,表達式2”,執行順序是先計算表達式1的值,再計算表達式2的值。表達式也可以擴展為“表達式1,表達式2,表達式3,…,表達式n”。

c=(a=3,2*a);

是将一個逗号表達式的值賦給變量c,第一個表達式a=3,第二個表達式2*a,計算得到6,因此變量c的值是6。

代碼d=a=b=3,2*a;整個是一個逗号表達式,這裡逗号表達式的值同樣是2*a的值,結果是6。但是變量d的值是在第一個表達式中計算得到的,得到值為3。

在使用逗号運算符的時候,要注意它的優先級和結合順序。逗号運算符優先級最低,丼且是自左至右結合的。

5 自增運算的不同寫法在效率上的一點區别

x = x 1,x = 1,x ,這三個表達式哪個執行效率最高?

第一個表達式x=x 1的執行過程是先讀取等号右邊的x的地址,計算x 1的值,然後讀取等号左邊的x的地址,最後将等号右邊的值傳給等号左邊的值。

第二個表達式x =1的執行過程是先讀取等号右邊的x的地址,然後計算x 1的值,最後将得到的值傳給左邊的x,因為x的地址已在前面讀出,故省去了傳值過程;

第三個表達式的執行過程是先讀取x的地址,然後x自增1;

因此,x 的效率最高。

編譯器優化後彙編代碼應該是一樣的。

從彙編來看前自增與後自增的區别:

7: a=c ; 004016AF mov eax,dword ptr [ebp-0Ch] 004016B2 mov dword ptr [ebp-4],eax 004016B5 mov ecx,dword ptr [ebp-0Ch] 004016B8 add ecx,1 004016BB mov dword ptr [ebp-0Ch],ecx 8: b= c; 004016BE mov edx,dword ptr [ebp-0Ch] 004016C1 add edx,1 004016C4 mov dword ptr [ebp-0Ch],edx 004016C7 mov eax,dword ptr [ebp-0Ch] 004016CA mov dword ptr [ebp-8],eax

6 switch語句效率入口與出口

switch相對于if…else if,具有較高的運行效率。因為switch會在編譯期建立一個跳轉列表,運行時可以根據跳轉列表進行直接跳轉。

在switch語句中,當找到與swith表達式相等的case時,執行case下的語句。case下的所有語句都執行完成後,如果一直沒有break,那麼程序将會執行到下一個case,而不管它的值是否與switch表達式相等,即多個case之間不具有天然的互斥性。要想使程序執行完一個case後的語句,而不進入下一個case,必須使用break語句,使程序退出switch結構。這樣,後面的case也就不執行了。

C語言一個分支的結束是依賴break完成的。case隻決定—序到哪裡執行,而不決定到哪裡結束。結束位置由break來決定,沒有break就一直執行到switch完整結構結束。

所以,case是swithc語句的入口(特殊情況下也可以是default),而由break提供出口(特殊情況下是最後一條case語句的結束塊符号“}”或return。

7 聯合體變量賦初值

由于聯合體變量具有所有成員共享一個内存地址的特點,因此為聯合體變量賦初值時隻能給該變量的第一個成員賦初值,其他成員不能賦初值。例如:

union number { int i; char c; float f; }m={2};

8 數組名

數組名是一指針常量,所以不能被再次賦值。隻能對其數據元素逐一操作。

數組名做函數參數時退化為指針,在函數體内不能得到其長度。

二維數組名并不能賦給一個二次指針,隻能賦給一個數組指針,或通過強制類型轉換,賦給一個一次指針:

int arr[5][5] = {1,2,3,4,5,6,7,8}; int (*pa)[5] = arr; int *p = (int*)arr; cout<<*pa[1] 2<<endl; // 8 cout<<*(p 7)<<endl; // 8

指針變量聲明并指向目标地址時,由類型信息決定目标内存空間的字節長度,當其指向一個n維數組時,其長度信息為一個n-1維數組的字節長度,所以n維數組指針聲明時需要顯式指定除第一維以外的其它長度信息。

指針數組名在語法層面等價于一個二級指針。

9 内在管理函數及庫中一些算法的參數和返回值的void類型

malloc、sort等函數的參數和返回值都使用void類型。原因是C是一門強類型語言,又沒有類型模闆機制來做泛型表示。

void指針隻能單純表示地址信息,其附加的類型信息不存在,所以其為一個不完全類型,隻能用于聲明和傳址,當需要解引用或做指針算術運算時,其類型信息附加的字節長度信息不可或缺,所以需有具體類型的強制轉換。

-End-

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关圖文资讯推荐

热门圖文资讯推荐

网友关注

Copyright 2023-2025 - www.tftnews.com All Rights Reserved