![](/img/trans.png)
[英]In function ‘int main(int, char**), ‘MIN’ was not declared
[英]Memory waste? If main() should only return 0 or 1, why is main declared with int and not short int or even char?
例如:
#include <stdio.h>
int main (void) /* Why int and not short int? - Waste of Memory */
{
printf("Hello World!");
return 0;
}
為什么main()
是常規定義為int
類型,它在 32 位上分配 memory 中的 4 個字節,如果它通常只返回 0 或 1,而其他類型如short int
(2 bytes,32-bit) 甚至char
( 1 字節,32 位)會更節省 memory 嗎?
它正在浪費 memory 空間。
注意:這個問題不是給定線程的重復; 它的答案只對應於返回值本身,而不對應於其明確關注的數據類型。
問題是針對 C 和 C++。 如果這些之間的答案發生變化,請分享您的智慧,並提及特別關注哪種語言的上下文。
通常匯編器使用它們的寄存器來返回一個值(例如 Intel 處理器中的寄存器AX
)。 int 類型對應於機器字,即不需要將例如char 類型對應的字節轉換為機器字。
事實上, main 可以返回任何 integer 值。
這是因為一台有半個世紀歷史的機器。
早在創建 C 的那一天, int
是 PDP-11 上的機器字 - 16 位 - 擁有main
返回是自然而有效的。
“機器字”是 B 語言中唯一的類型,它是 Ritchie 和 Thompson 較早開發的,並且是從 C 發展而來的。
當 C 添加類型時,不指定一個給你一個機器字 - 一個int
。
(當時節省空間非常重要,所以不需要拼出最常見的類型是一件非常好的事情。)
因此,由於 B 程序以
main()
程序員通常是語言保守的,C 做了同樣的事情並返回了一個int
。
我不認為這是浪費的原因有兩個:
如果要返回一個准確描述錯誤的退出代碼,則需要超過 8 位。
例如,您可能希望對錯誤進行分組:第一個字節可以描述模糊的錯誤類型,第二個字節可以描述導致錯誤的 function,第三個字節可以提供有關錯誤原因的信息,第四個字節描述額外的調試信息。
如果您傳遞單個short 或 char,它們仍將對齊以適合機器字,這通常是 4 字節/32 位,具體取決於架構。 這稱為填充,意味着您很可能仍需要 32 位 memory 來返回單個短字符或字符。
大多數 shell 的老式約定是使用int
的最低有效 8 位,而不僅僅是 0 或 1。16 位越來越普遍,因為這是標准允許的int
的最小大小。
浪費空間會有什么問題? 空間真的浪費了嗎? 您的計算機是否充滿了“東西”,以至於剩余的sizeof(int) * CHAR_BIT - 8
會有所作為? 該架構能否利用這一點並將剩余的部分用於其他用途? 我非常懷疑。
所以我不會說 memory 完全被浪費了,因為你在程序完成時從操作系統中取回它。 也許奢侈? 有點像用一個大酒杯喝一小杯酒?
第一: if it usually returns only 0 or 1
單獨你的假設/陳述是錯誤的。
通常,如果沒有發生錯誤,則返回代碼應為0
,否則它可以返回任何數字來表示不同的錯誤。 大多數(至少命令行程序)都這樣做。 許多程序還 output 負數。
However there are a few common used codes https://www.tldp.org/LDP/abs/html/exitcodes.html
also here another SO member points to a unix header that contains some codes https://stackoverflow.com/a /24121322/2331592
因此,畢竟它不僅僅是C
或C++
類型的東西,而且還有大多數操作系統如何工作並期望程序運行的歷史原因,因為語言必須支持這一點,所以至少C
使用 an12F80B84D1 之類的語言這樣做int main(...)
。
第二:你的結論It is wasting memory space
是錯誤的。
int
不會造成任何浪費。 無論如何,Memory 通常以字長處理(這意味着可能取決於您的架構)return 0;
此時從未使用過 memory。 如果您return myMemorySaving8bitVar;
您只使用了 1 個字節(最有可能在堆棧上(如果根本沒有優化))答案是“因為它通常不會只返回 0 或 1”。 我從軟件工程社區找到了這個帖子,它至少部分回答了你的問題。 以下是兩個亮點,首先來自已接受的答案:
integer 為報告錯誤提供了比一個字節更多的空間。 它可以被枚舉(返回 1 表示 XYZ,返回 2 表示 ABC,返回 3,表示 DEF 等)或用作標志(
0x0001
表示失敗,0x0002
表示失敗,0x0003
表示失敗和失敗)。 將其限制為僅一個字節很容易用完標志(只有 8 個),因此決定可能是使用 integer。
Keith Thompson還提出了一個有趣的觀點:
例如,在Plan 9操作系統中使用的 C 的方言中,
main
通常聲明為void
function,但是通過將字符串指針傳遞給exits()
ZC1C425268E68A47,將退出狀態返回給調用環境。 空字符串表示成功,任何非空字符串表示某種失敗。 這可以通過讓main
返回一個char*
結果來實現。
這是來自unix.com 論壇的另一個有趣的部分:
(以下一些可能是 x86 特定的。)
回到原來的問題:退出狀態存儲在哪里? kernel 內部。
當您調用 exit(n) 時,integer n 的最低有效 8 位被寫入 cpu 寄存器。 然后 kernel 系統調用實現會將其復制到與流程相關的數據結構中。
如果你的代碼沒有調用exit()怎么辦? 負責調用 main() 的 c 運行時庫將代表您調用 exit() (或其一些變體)。 main() 的返回值在寄存器中傳遞給 c 運行時,用作 exit() 調用的參數。
與最后一個報價相關,這是來自cppreference.com的另一個報價
5) 執行返回(或到達 main 結束時的隱式返回)等價於先正常離開 function(這會破壞具有自動存儲持續時間的對象),然后使用與參數相同的參數調用 std::exit的回報。 (std::exit 然后銷毀 static 對象並終止程序)
最后,我在這里找到了這個非常酷的示例(盡管帖子的作者說返回的結果是返回值模 512 是錯誤的)。 編譯並執行以下命令后:
int main() {
return 42001;
}
在
符合 POSIX 的
my* 系統上, echo $?
返回 17。那是因為42001 % 256 == 17
這表明實際使用了 8 位數據。 考慮到這一點,選擇int
可確保有足夠的存儲空間可用於傳遞程序的退出狀態信息,因為根據此答案,符合 C++ 標准可確保int
的大小(以位為單位)
不能小於8。這是因為它必須足夠大以容納“Unicode UTF-8編碼形式的八位代碼單元”。
編輯:
*正如Andrew Henle在評論中指出的那樣:
完全符合 POSIX 的系統使整個
int
返回值可用,而不僅僅是 8 位。 請參閱pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html :“如果si_code
等於CLD_EXITED
,則si_status
保存進程的退出值;否則,它等於導致進程更改 state.si_status
中的退出值應等於完整退出值(即傳遞給_exit()
、_Exit()
或exit()
的值,或從main()
返回的值);不受限制到該值的最低有效八位。”
我認為這為使用int
而不是較小大小的數據類型提供了更強有力的論據。
您正在工作或學習 C,所以我認為您關心效率是一個真正的好主意。 但是,這里似乎有幾件事需要澄清。
首先, int 數據類型並不是“32 位”的意思。 這個想法是 int 將是目標機器上最自然的二進制 integer 類型——通常是寄存器的大小。
其次,來自 main() 的返回值旨在適應不同操作系統上的各種實現。 POSIX 系統使用無符號的 8 位返回碼。 Windows 使用由 CMD shell 解釋為 2 的補碼符號的 32 位。 另一個操作系統可能會選擇其他東西。
最后,如果您擔心 memory “浪費”,那么在這種情況下,這是一個實現問題,甚至不是問題。 來自 main 的返回碼通常在機器寄存器中返回,而不是在 memory 中,因此不涉及成本或節省。 即使有,在運行一個重要程序時節省 2 個字節也不值得任何開發人員的時間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.