![](/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.