[英]Why is there no inbuilt swap function in C but there is xchg in Assembly?
最近我遇到了匯編語言。 x86程序集有一個xchg指令 ,用於交換兩個寄存器的內容。
由於每個C代碼都首先轉換為匯編代碼,如果在標頭stdio.h
有一個內置的交換函數,那就太好了。 然后,只要編譯器檢測到交換函數,它就可以在匯編文件中添加xchg指令。
那么為什么這個交換功能沒有在C中實現呢?
C是一種跨平台語言。 裝配是特定於架構的。 並非每個架構都有這樣的指令。 而且,作為高級語言的C不必與機器級指令集和功能相對應,因為它的目的是在“人”語言和機器語言之間架起橋梁,而不是模仿它。 據說,針對此特定體系結構的C編譯器可能具有此交換指令的擴展,或者如果足夠智能則優化交換代碼以使用此指令。
這適用於適合寄存器並位於寄存器中的變量。 它不適用於內存中保存的大型結構或變量(如果在reg X中加載變量A,在reg Y中加上B,並交換它們,則可以跳過交換並直接在Y和B中加載A )。
話雖如此,沒有什么能阻止編譯器使用交換指令進行編譯:
int a;
int b;
int tmp;
tmp=a;
a=b;
b=tmp;
...如果那些恰好在寄存器中:事實上它不在C中並不意味着編譯器不使用它。
有兩點可以解釋為什么swap()
不在C中
1.函數調用語義:
包含swap()
函數會在C中打破一個非常基本的設計決策: swap()
只能使用pass-by-reference語義(C ++添加到語言中,但C語言中沒有),而不是pass-by -值。
2.可用匯編程序指令的多樣性
除此之外,在任何給定的CPU架構上通常都有相當多的匯編指令,它們完全無法從純C中訪問。這包括各種指令,如中斷處理指令,虛擬存儲空間操作指令,I / O指令,位功能指令(谷歌PPC指令rlwimi
是一個特別有力的例子),等等。
在像C這樣的通用語言中包含任何大量的這些都是不可能的。
其中一些對於實現操作系統至關重要,這就是為什么任何操作系統必須至少包含一些少量的匯編代碼。 它們通常使用內聯匯編程序封裝在某些函數中,或者在內核頭文件中定義為預處理程序指令。 其他指令不太重要,或者只對優化很有用,這些指令可以通過優化編譯器生成,並且許多編譯器確實生成它們(整個類的向量函數都屬於這一類)。
面對這種巨大的多樣性,C的設計師不得不將它切割到某個地方。 他們選擇提供任何可表示的簡單操作符,如(+, - ,〜,&,|,!,&&,||等),但沒有提供任何需要函數調用語法的東西,如swap()
你建議的功能。
除了其他正確答案所說的,你的前提的另一部分是錯誤的。
每次源交換變量時,只有一個非常愚蠢的編譯器才會想要實際發出xchg
,無論是否存在內在函數或運算符。 優化編譯器不只是將C音譯成asm,它們通常轉換為程序邏輯的SSA內部表示,並對其進行優化,以便它們可以用盡可能少的指令實現它(或者實際上以最有效的方式實現;使用多個快速指令可能比單個慢速指令更好。
xchg
很少比3 mov
指令快,並且一個好的編譯器可以簡單地改變它的本地變量< - > CPU寄存器映射,而在許多情況下不發出任何asm指令。 (或者在循環內部,展開通常可以優化遠程交換。)通常你只需要asm中的1或mov
指令,而不是全部3.例如,如果只有一個被交換的C變量需要保留在同一個寄存器中,你可以做:
# start: x in EAX, y in ECX
mov edx, eax
mov eax, ecx
# end: y in EAX, x in EDX
另請參閱為什么XCHG reg,注冊了關於現代英特爾架構的3微操作指令?
另請注意, xchg [mem], reg
是原子(隱式lock
前綴),因此是一個完整的內存屏障,比3個mov
指令慢得多,並且由於內存屏障效應對周圍代碼的影響要大得多。
如果你確實需要交換寄存器,3 mov
是相當不錯的。 通常比xchg reg,reg
更好xchg reg,reg
因為xchg reg,reg
了mov
,代價是更多代碼大小和tmp reg。
編譯器從不使用xchg
是有原因的。 如果xchg
是一個勝利,編譯器會將其視為窺視孔優化,就像它們在add eax,1
或xor eax,eax
而不是mov eax,0
查找inc eax
一樣。 但他們沒有。
(半相關: 用8086匯編語言(16位)交換2個寄存器 )
盡管xchg
是一個非常基本的指令,但這並不意味着C必須具有等效性。 C 有時直接映射到裝配的事實並不十分重要; 標准沒有提到“匯編”(為什么映射到匯編而不是另一種低級語言?)。
您可能還會問:為什么C沒有內置向量指令? 他們變得很有可能!
還有編譯器的幫助:交換變量是一種非常明顯的模式,因此這種優化應該不難實現。 如果需要,你也有內聯asm
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.