内存浪费?如果 main() 应该只 return 0 或 1,为什么 main 声明为 int 而不是 short int 甚至 char?
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位上分配4个字节在内存中,如果通常returns只有0或1,而其他类型例如 short int
(2 字节,32 位)甚至 char
(1 字节,32 位)会节省更多内存吗?
它正在浪费内存 space。
注意:问题不是给定线程的重复;它的答案仅对应于 return 值本身,而不对应于其在明确焦点处的数据类型。
问题是针对 C 和 C++ 的。如果这些之间的答案有所不同,请分享您的智慧,并提及特别关注哪种语言的上下文。
通常汇编程序使用他们的寄存器来 return 一个值(例如 Intel 处理器中的寄存器 AX
)。 int类型对应机器字 即不需要将例如char类型对应的byte转换为机器字
事实上,main 可以 return 任何整数值。
大多数 shell 的老式约定是使用 int
的最低有效 8 位,而不仅仅是 0 或 1。16 位越来越普遍,因为它是 [= 的最小大小10=] 标准允许。
浪费 space 会有什么问题? space真的浪费了吗?您的计算机是否充满了 "stuff",以至于剩余的 sizeof(int) * CHAR_BIT - 8
会有所不同?该体系结构能否利用它并将那些剩余的位用于其他用途?我很怀疑。
所以我不会说内存完全被浪费了,因为当程序完成时,您会从操作系统中取回内存。也许奢侈?有点像用大酒杯喝小酒?
我不认为这是浪费的原因有两个:
1 4字节退出码的实际使用
如果您想要 return 一个准确描述错误的退出代码,您需要超过 8 位。
例如,您可能希望对错误进行分组:第一个字节可以描述错误的模糊类型,第二个字节可以描述导致错误的函数,第三个字节可以提供有关错误原因的信息第四个字节描述了额外的调试信息。
2 填充
如果您传递 single short 或 char,它们仍将对齐以适应机器字,通常为 4 Byte/32 位,具体取决于体系结构。这称为填充,意味着您很可能仍需要 32 位内存来 return a single short 或 char.
因为有半个世纪的机器
在创建 C 的那一天,int
是 PDP-11 上的一个机器字 - 十六位 - main
[=28= 是自然而有效的] 那。
"machine word" 是 B 语言中唯一的类型,Ritchie 和 Thompson 较早地开发了它,C 也从中发展而来。
当 C 添加类型时,不指定一个会给你一个机器字 - int
.
(当时节省space非常重要,所以不要求拼出最常见的类型是一件非常好的事情。)
所以,由于 B 程序开始于
main()
而且程序员通常对语言很保守,C 也是如此,return编辑了一个 int
。
第一:单独你的assumption/statementif it usually returns only 0 or 1
是错误的。
通常,如果没有发生错误,return 代码应该是 0
,否则它可以 return 任何数字来表示不同的错误。大多数(至少命令行程序)都是这样做的。许多程序也输出负数。
但是有一些常用的代码https://www.tldp.org/LDP/abs/html/exitcodes.html
这里还有另一个 SO 成员指向一个包含一些代码的 unix 头文件
所以毕竟它不仅仅是 C
或 C++
类型的东西,而且还有历史原因大多数操作系统如何工作并期望程序的行为,因为语言必须支持那等等至少 C
类似的语言通过使用 int main(...)
.
来做到这一点
第二名:
你的结论It is wasting memory space
是错误的。
- 与较短的类型相比,使用
int
不会造成任何浪费。
无论如何,内存通常以字大小处理(这意味着可能取决于您的体系结构)
- 使用子字类型涉及某些体系结构上的计算开销(读取:加载,字,屏蔽掉不相关的位;存储:加载内存,屏蔽掉可变位,或者用新值将它们写入字返回)
- 除非您使用它,否则内存不会浪费。如果你写
return 0;
此时没有内存被使用。如果你 return myMemorySaving8bitVar;
你只使用了 1 个字节(最有可能在堆栈上(如果根本没有优化))
答案是 "because it usually doesn't return only 0 or 1." 我发现 this thread 来自软件工程社区,至少部分回答了您的问题。这是两个亮点,首先来自已接受的答案:
An integer gives more room than a byte for reporting the error. It can be enumerated (return of 1 means XYZ, return of 2 means ABC, return of 3, means DEF, etc..) or used as flags (0x0001
means this failed, 0x0002
means that failed, 0x0003
means both this and that failed). Limiting this to just a byte could easily run out of flags (only 8), so the decision was probably to use an integer.
Keith Thompson也提出了一个有趣的观点:
For example, in the dialect of C used in the Plan 9 operating system main
is normally declared as a void
function, but the exit status is returned to the calling environment by passing a string pointer to the exits()
function. The empty string denotes success, and any non-empty string denotes some kind of failure. This could have been implemented by having main
return a char*
result.
这是来自 unix.com forum 的另一个有趣的片段:
(Some of the following may be x86 specific.)
Returning to the original question: Where is the exit status stored? Inside the kernel.
When you call exit(n), the least significant 8 bits of the integer n are written to a cpu register. The kernel system call implementation will then copy it to a process-related data structure.
What if your code doesn't call exit()? The c runtime library responsible for invoking main() will call exit() (or some variant thereof) on your behalf. The return value of main(), which is passed to the c runtime in a register, is used as the argument to the exit() call.
与上一条引述相关,这是来自 cppreference.com
的另一引述
5) Execution of the return (or the implicit return upon reaching the end of main) is equivalent to first leaving the function normally (which destroys the objects with automatic storage duration) and then calling std::exit with the same argument as the argument of the return. (std::exit then destroys static objects and terminates the program)
最后,我发现了这个非常酷的例子here(虽然post的作者说返回的结果是模512的返回值是错误的)。编译并执行以下命令后:
int main() {
return 42001;
}
on a POSIX compliant my* system, echo $?
returns 17. 那是因为 42001 % 256 == 17
这表明实际使用了 8 位数据。考虑到这一点,选择 int
可确保有足够的存储空间可用于传递程序的退出状态信息,因为根据 this answer,符合 C++ 标准可保证 int
的大小(以位为单位)
can't be less than 8. That's because it must be large enough to hold "the eight-bit code units of the Unicode UTF-8 encoding form."
编辑:
*正如 Andrew Henle 在评论中指出的那样:
A fully POSIX compliant system makes the entire int
return value available, not just 8 bits. See pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html: "If si_code
is equal to CLD_EXITED
, then si_status
holds the exit value of the process; otherwise, it is equal to the signal that caused the process to change state. The exit value in si_status
shall be equal to the full exit value (that is, the value passed to _exit()
, _Exit()
, or exit()
, or returned from main()
); it shall not be limited to the least significant eight bits of the value."
我认为这为在较小的数据类型上使用 int
提供了更有力的论据。
您正在使用 C 或正在学习 C,所以我认为您关注效率是一个真正的好主意。但是,这里似乎有几件事似乎需要澄清。
首先,int 数据类型并非意指“32 位”。这个想法是 int 将是目标机器上最自然的二进制整数类型——通常是寄存器的大小。
其次,main() 中的 return 值旨在适应不同操作系统上的广泛实施。 POSIX 系统使用无符号的 8 位 return 代码。 Windows 使用被 CMD shell 解释为 2 的补码符号的 32 位。另一个 OS 可能会选择其他东西。
最后,如果您担心内存 "waste",那是一个实施问题,在这种情况下甚至不是问题。 Return 来自 main 的代码通常 return 在机器寄存器中编辑,而不是在内存中,因此不涉及成本或节省。即使有,在一个重要程序的 运行 中节省 2 个字节也不值得任何开发人员花费时间。
例如:
#include <stdio.h>
int main (void) /* Why int and not short int? - Waste of Memory */
{
printf("Hello World!");
return 0;
}
为什么main()
是约定俗成的用int
类型定义的,它在32位上分配4个字节在内存中,如果通常returns只有0或1,而其他类型例如 short int
(2 字节,32 位)甚至 char
(1 字节,32 位)会节省更多内存吗?
它正在浪费内存 space。
注意:问题不是给定线程的重复;它的答案仅对应于 return 值本身,而不对应于其在明确焦点处的数据类型。
问题是针对 C 和 C++ 的。如果这些之间的答案有所不同,请分享您的智慧,并提及特别关注哪种语言的上下文。
通常汇编程序使用他们的寄存器来 return 一个值(例如 Intel 处理器中的寄存器 AX
)。 int类型对应机器字 即不需要将例如char类型对应的byte转换为机器字
事实上,main 可以 return 任何整数值。
大多数 shell 的老式约定是使用 int
的最低有效 8 位,而不仅仅是 0 或 1。16 位越来越普遍,因为它是 [= 的最小大小10=] 标准允许。
浪费 space 会有什么问题? space真的浪费了吗?您的计算机是否充满了 "stuff",以至于剩余的 sizeof(int) * CHAR_BIT - 8
会有所不同?该体系结构能否利用它并将那些剩余的位用于其他用途?我很怀疑。
所以我不会说内存完全被浪费了,因为当程序完成时,您会从操作系统中取回内存。也许奢侈?有点像用大酒杯喝小酒?
我不认为这是浪费的原因有两个:
1 4字节退出码的实际使用
如果您想要 return 一个准确描述错误的退出代码,您需要超过 8 位。
例如,您可能希望对错误进行分组:第一个字节可以描述错误的模糊类型,第二个字节可以描述导致错误的函数,第三个字节可以提供有关错误原因的信息第四个字节描述了额外的调试信息。
2 填充
如果您传递 single short 或 char,它们仍将对齐以适应机器字,通常为 4 Byte/32 位,具体取决于体系结构。这称为填充,意味着您很可能仍需要 32 位内存来 return a single short 或 char.
因为有半个世纪的机器
在创建 C 的那一天,int
是 PDP-11 上的一个机器字 - 十六位 - main
[=28= 是自然而有效的] 那。
"machine word" 是 B 语言中唯一的类型,Ritchie 和 Thompson 较早地开发了它,C 也从中发展而来。
当 C 添加类型时,不指定一个会给你一个机器字 - int
.
(当时节省space非常重要,所以不要求拼出最常见的类型是一件非常好的事情。)
所以,由于 B 程序开始于
main()
而且程序员通常对语言很保守,C 也是如此,return编辑了一个 int
。
第一:单独你的assumption/statementif it usually returns only 0 or 1
是错误的。
通常,如果没有发生错误,return 代码应该是 0
,否则它可以 return 任何数字来表示不同的错误。大多数(至少命令行程序)都是这样做的。许多程序也输出负数。
但是有一些常用的代码https://www.tldp.org/LDP/abs/html/exitcodes.html
这里还有另一个 SO 成员指向一个包含一些代码的 unix 头文件
所以毕竟它不仅仅是 C
或 C++
类型的东西,而且还有历史原因大多数操作系统如何工作并期望程序的行为,因为语言必须支持那等等至少 C
类似的语言通过使用 int main(...)
.
第二名:
你的结论It is wasting memory space
是错误的。
- 与较短的类型相比,使用
int
不会造成任何浪费。 无论如何,内存通常以字大小处理(这意味着可能取决于您的体系结构) - 使用子字类型涉及某些体系结构上的计算开销(读取:加载,字,屏蔽掉不相关的位;存储:加载内存,屏蔽掉可变位,或者用新值将它们写入字返回)
- 除非您使用它,否则内存不会浪费。如果你写
return 0;
此时没有内存被使用。如果你return myMemorySaving8bitVar;
你只使用了 1 个字节(最有可能在堆栈上(如果根本没有优化))
答案是 "because it usually doesn't return only 0 or 1." 我发现 this thread 来自软件工程社区,至少部分回答了您的问题。这是两个亮点,首先来自已接受的答案:
An integer gives more room than a byte for reporting the error. It can be enumerated (return of 1 means XYZ, return of 2 means ABC, return of 3, means DEF, etc..) or used as flags (
0x0001
means this failed,0x0002
means that failed,0x0003
means both this and that failed). Limiting this to just a byte could easily run out of flags (only 8), so the decision was probably to use an integer.
Keith Thompson也提出了一个有趣的观点:
For example, in the dialect of C used in the Plan 9 operating system
main
is normally declared as avoid
function, but the exit status is returned to the calling environment by passing a string pointer to theexits()
function. The empty string denotes success, and any non-empty string denotes some kind of failure. This could have been implemented by havingmain
return achar*
result.
这是来自 unix.com forum 的另一个有趣的片段:
(Some of the following may be x86 specific.)
Returning to the original question: Where is the exit status stored? Inside the kernel.
When you call exit(n), the least significant 8 bits of the integer n are written to a cpu register. The kernel system call implementation will then copy it to a process-related data structure.
What if your code doesn't call exit()? The c runtime library responsible for invoking main() will call exit() (or some variant thereof) on your behalf. The return value of main(), which is passed to the c runtime in a register, is used as the argument to the exit() call.
与上一条引述相关,这是来自 cppreference.com
的另一引述5) Execution of the return (or the implicit return upon reaching the end of main) is equivalent to first leaving the function normally (which destroys the objects with automatic storage duration) and then calling std::exit with the same argument as the argument of the return. (std::exit then destroys static objects and terminates the program)
最后,我发现了这个非常酷的例子here(虽然post的作者说返回的结果是模512的返回值是错误的)。编译并执行以下命令后:
int main() {
return 42001;
}
on a POSIX compliant my* system, echo $?
returns 17. 那是因为 42001 % 256 == 17
这表明实际使用了 8 位数据。考虑到这一点,选择 int
可确保有足够的存储空间可用于传递程序的退出状态信息,因为根据 this answer,符合 C++ 标准可保证 int
的大小(以位为单位)
can't be less than 8. That's because it must be large enough to hold "the eight-bit code units of the Unicode UTF-8 encoding form."
编辑:
*正如 Andrew Henle 在评论中指出的那样:
A fully POSIX compliant system makes the entire
int
return value available, not just 8 bits. See pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html: "Ifsi_code
is equal toCLD_EXITED
, thensi_status
holds the exit value of the process; otherwise, it is equal to the signal that caused the process to change state. The exit value insi_status
shall be equal to the full exit value (that is, the value passed to_exit()
,_Exit()
, orexit()
, or returned frommain()
); it shall not be limited to the least significant eight bits of the value."
我认为这为在较小的数据类型上使用 int
提供了更有力的论据。
您正在使用 C 或正在学习 C,所以我认为您关注效率是一个真正的好主意。但是,这里似乎有几件事似乎需要澄清。
首先,int 数据类型并非意指“32 位”。这个想法是 int 将是目标机器上最自然的二进制整数类型——通常是寄存器的大小。
其次,main() 中的 return 值旨在适应不同操作系统上的广泛实施。 POSIX 系统使用无符号的 8 位 return 代码。 Windows 使用被 CMD shell 解释为 2 的补码符号的 32 位。另一个 OS 可能会选择其他东西。
最后,如果您担心内存 "waste",那是一个实施问题,在这种情况下甚至不是问题。 Return 来自 main 的代码通常 return 在机器寄存器中编辑,而不是在内存中,因此不涉及成本或节省。即使有,在一个重要程序的 运行 中节省 2 个字节也不值得任何开发人员花费时间。