我記得在某個地方讀最好用整數作爲循環計數器變量而不是char或short。如果是,爲什麼?它是否提供了任何優化優勢?使用整數作爲循環計數器變量會更好嗎?
回答
通常,編譯器會將int
設置爲放入CPU的通用寄存器中的一個很好的大小。這通常會導致快速訪問。
當然,沒有任何保證。編譯器可以自由地做很多事情,包括我猜想,將一些使用char
的代碼提升爲更大的類型。所以差異可能無關緊要。
真的,對於爲您編譯器是真的答案,你應該看看它輸出組件。
在32位體系結構中,使用4個字節(int)變量的操作通常更快。這主要是由於寄存器和內存對齊的大小。在64位體系結構中,int將(應該)自動成爲64位整數。
int
類型通常可以預期爲您平臺上實現速度最快的整數類型,因此應該是默認選擇。
從K & R,第2版, 36:
int
:一個整數,通常反映主機上整數的自然大小。
啊,沒什麼像那裏的錯誤概括。您可以使用整數實現超越函數,不會像使用浮點處理器的浮點一樣快。此外,數組中的值可以適合char的int數組將需要四倍的內存帶寬進行處理。 – Skizz 2010-02-11 09:35:45
將其更改爲「最快實施的整數類型」。 – 2010-02-11 09:38:58
對於循環計數器使用size_t
類型會更好。它將擴展到64位。
一個循環,確實2^64-1會嚇到我:D – 2010-02-11 09:34:10
你不必從0開始並以最大可能值結束xD – fortran 2010-02-11 09:46:44
我們通常會在2以上運行^ 31-1在未來幾年。我們的代碼爲此做好了準備。 – 2010-02-11 09:51:12
在某些情況下,使用char
(或甚至short
s)的溢出問題將產生非終止循環。
阿列克謝*是正確的,它通常更快地使用一種類型是這樣的寬度相同的體系結構(即,對於32位系統中的INT32)
此外,如果使用一個char即
for(char i=0;i<max;++i)
有輕微的機會,你(或同事)會回來的代碼在一個月的時間,變化最大的東西高,造成溢出和惱人的錯誤;)
山姆
*以及其他在我寫這篇文章時回答的人!
有沒有注意到C標準對於整數是多少?這一事實驅使設備驅動程序工程師和從事通信協議的工程師變得非常沮喪,因爲他們認爲語言應該明確定義對象的大小。
C表示int
是實現架構的自然大小。這意味着它的處理將至少與其他任何規模一樣有效。採用x86體系結構:在32位程序中使用的short
(16位整數)包含執行額外「大小重寫」修改的指令。所以代碼有更多的字節,但通常沒有性能損失。除非額外的字節導致高速緩存線溢出....
對於char
計數器,x86生成的代碼通常包括在增量後進行掩碼以確保其保持8位。看起來使用更小的變量會更小,更緊湊,但x86和其他幾個常見CPU並不是這種情況。
這實際上取決於您編寫的代碼平臺。使用的最佳類型是將其與您的平臺相匹配。也就是說,如果您正在編寫簡單的8位微代碼,也許使用uint8_t比使用uint16_t更好。
在擔心這個問題之前擔心讓你的循環正確。通過更改int
,char
或short
之間的循環計數器的類型,您可能在循環邊界內發生錯誤,而不是速度或代碼大小的可測量差異。所以先擔心正確性。
也就是說,默認使用int
或unsigned int
,除非您有其他理由 - 但我這樣說是因爲您不太可能需要擔心溢出或繞過較大的類型,而不是因爲它可能會更快(儘管可能)。
這真的取決於你的循環在做什麼。以這個循環爲例:
typedef struct _SomeData
{
/* some data here */
} SomeData;
void SomeFunction (SomeData *array_of_data, int number_of_elements)
{
int i;
for (i = 0 ; i < number_of_elements ; ++i)
{
DoSomethingWithData (&array_of_data [i]);
}
}
一些編譯器會很好地優化以上。但是一些編譯器,尤其是利基嵌入式微處理器的編譯器,將會產生非常糟糕的代碼。它可以重新寫爲:
void SomeFunction (SomeData *array_of_data, int number_of_elements)
{
SomeData *current = array_of_data, *end = &array_of_data [number_of_elements];
while (current < end)
{
DoSomethingWithData (current++);
}
}
這完全不使用整數,並且更容易產生良好的輸出,無論編譯器(現代編譯器很可能會在整數版本優化,以類似上述無論如何)。
因此,整數並不總是循環所必需的,最好的優化總是不做不必要的事情。但是,如果循環明確需要整數,那麼int類型通常會提供最好的結果。
當然,您必須始終使用探查器來確定代碼的性能以及是否改變類型有什麼不同。
通常,int是循環的正確選擇。有兩個原因可能不是:
- 它可能比需要的大。 SDCC支持一些8位處理器,例如允許8位訪問寄存器的Z80,儘管sizeof(int)= 2。如果您的循環變量不需要多於8位,那麼使用sizeof(char)= 1的chars可以使優化器將更多內存填充到寄存器空間中,從而實現更快的代碼。
- 它可能太小了。如果整數是16位,那麼你可能會有循環運行多次。
所以,是的,您可能需要考慮您的架構有多大。但通常你不會。
- 1. 我可以使用寄存器作爲循環計數器嗎?
- 2. 使用公共整數變量作爲計數器C#
- 3. 這會更好地使用循環而不是函數嗎?
- 4. 計數器變量作爲Python中for循環的步進值
- 5. 使用計數器作爲變量
- 6. 在循環內部還是在循環外部聲明變量會更好嗎?
- 7. MS Access 2010 VBA整數變量不會在循環中更改
- 8. 如何使用計數器作爲for循環中的變量擴展?
- 9. 使用8位無符號整數變量作爲計數器循環256個值
- 10. 這個循環數據引用可以設計得更好嗎?
- 11. 爲什麼在Java中更改循環計數器不好?
- 12. 變量R中循環作爲函數
- 13. JavaScript函數作爲循環變量
- 14. 函數爲循環變量
- 15. 更好倒塌循環指數計算
- 16. 使用變量定義嵌套for循環中的計數器
- 17. 使用其他變量作爲計數器創建JavaScript變量
- 18. 遞增循環中的整數變量
- 19. 使用用戶的輸入作爲循環計數器
- 20. 使用計數器製作Python3變量
- 21. While循環比For循環更好嗎?
- 22. 如何使用循環變量作爲參數
- 23. 使用循環變量作爲C++數組的索引
- 24. 循環中的變量計數
- 25. Verilog的:使用REG作爲計數器for循環
- 26. 在循環中使用字母作爲計數器
- 27. 通過使用浮點值作爲循環計數器
- 28. 使用sleep()或無限循環等待事件會更好嗎?
- 29. 循環變量作爲異步函數調用中的參數
- 30. For循環計數器停留嗎?
你是對的,但有許多8位微控制器(遠遠超過個人電腦和服務器),它們不能在一個寄存器中放入一個int。也許一個'uint8_fast_t'是最好的表現 – 12431234123412341234123 2017-03-07 12:17:58