为什么argc是'int'(而不是'unsigned int')?
为什么命令行参数计数variables(传统上是“argc”)是一个'int'而不是'unsigned int'? 有这个技术原因吗?
当我试图摆脱所有签名的无符号比较警告时,我总是忽略它,但从来没有理解为什么它是这样的。
事实上,原来的C语言是这样的, 默认情况下,任何variables或参数被定义为inttypes ,这可能是另一个因素。 换句话说,你可以有:
main(argc, char* argv[]); /* see remark below... */
而不是
int main(int argc, char *argv[]);
编辑 :正如Aaron提醒我们的,非常原始的语法应该是这样的
main(argc, argv) char **argv {... }
由于“原型”仅在后面才介绍。 这大概是在每个人都logging了至less10个小时追逐微妙(而不是那么微妙)types相关的错误
几个原因:
- 因为没关系
- 因为C本来没有
unsigned
关键字或无符号整数types - 因为C本来没有检查参数types,甚至没有原型。
因此,通常的做法是不要声明int
types,因为这是默认的。 - 因为从某种意义上来说,
int
在当时更为重要。 一切都是一个整数。 C部分来自一种甚至没有types的语言。 每一个可用的可扩展标记都是一个word
,这就是int
最初被用来做什么的。
更新: 贾森S要求来源。 我认为你可以从dmr的一篇论文中挖掘出所有这些(除了“没关系”),这就是在线的: C语言的发展 。 您可能需要在通常的位置查找较早的语言BCPL和B.
因为C很古老,而且从一开始就是这样devise的。 现在改变已经太迟了。
这是一个用dmr自己的话说的C编程语言的历史。 没有明确说明(至less不是从我提供的快速浏览),但最早版本的C不支持无符号types。 mjv关于隐式键入int
的观点也是相关的。
编辑
贝尔实验室的链接已被打破了一段时间: 这是一个替代链接到同一篇论文。
另一个原因可能是无符号types可能不方便迭代。 例如,这段代码重复执行:
for (size_t i = SIZE - 1; i >= 0; --i) ...
其实是一个错误。 当我在最后一次迭代中达到0时,它将进入4294967295(在32位机器上)并且循环不会终止。
出于这个原因,我个人觉得plain int更方便迭代。 使用整数时,从循环开始计数到倒计时,您不必特别小心。
Google C ++风格指南build议不要使用unsigned int
types,除非您使用实际的位模式。 他们的理由适用于C。 快速总结行:
C的types提升scheme导致无符号types的行为与预期的不同。 …不要使用无符号types。
这可能不在C的原创者的脑海里,但是谁知道呢?
作为警告问题的解决scheme,您可以这样做来抑制警告:
const unsigned int uargc = (unsigned int) argc;
由于Java中没有无符号types,所以将来将C程序移植到Java更容易。
main()
的声明是在将无符号types添加到语言之前定义的 – 请参阅DMR的' Primeval C '页面。 添加无符号时,更改已经太迟了。
我看到它可能看起来很奇怪: argc
不应该是负面的! 但是用这种方式来看看: int
和unsigned int
覆盖了你接受的值的范围(如果你有2 ^ 31个命令行参数,你有问题),而且int
types更短。
面试之谜问题:有多less键盘已经用完了inputunsigned
如果C已经用unsigned int argc
?
通过将其设置为int,范围被限制在1和INT_MAX之间(包括)。 这通常意味着没有意外的转换或别名会将其从无意中绕回来的范围中取出。 它还允许实现针对系统特定情况使用整个负数和0范围。
好的,我刚刚做了。 真正的原因是,原来的C语言开发者之一只是一个任意的决定,到现在为止还没有人真正想过。 🙂
只是一个简单的问题:你是否期望超过2 31 (甚至超过2 15 )的命令行参数? 我怀疑大多数操作系统可以处理那么多。
我认为它被devise为与C兼容,而在C时代,人们并不太在乎签名/未签名的正确性。