【问题标题】:Limit on the number of arguments to main in C限制 C 中 main 的参数数量
【发布时间】:2010-09-16 07:00:40
【问题描述】:

我们在 C 中传递给 main() 的参数数量是否有限制?众所周知,它被定义为int main(int argc, char *argv[])

当我调用程序时,我可以像这样传递参数:

$ prog.exe arg1 arg2 arg3.....argn

我们可以通过这种方式提供给main() 的参数数量是否有上限?

【问题讨论】:

标签: c language-lawyer


【解决方案1】:

根据exec 的POSIX 规范,<limits.h> 中定义了一个宏ARG_MAX,它定义了参数+环境变量的最大字节数。

但是由于 C 没有对此进行任何定义,因此不存在固有的跨平台限制。如果没有定义该宏,您必须查阅您的操作系统手册。

【讨论】:

  • 回复:exec() 系统调用。出于理智的原因,操作系统限制了它们必须从旧进程内存映像传输到正在创建的新进程内存映像的内存量。由于传输发生在内核中,因此必须限制以避免用户进程耗尽内核内存(想象一下fork/shell bomb)。在 Windows 上这无关紧要,因为旧进程仍然存在,但 IIRC 他们也将其限制为 32K。
  • limit.h 提供的值可能低于操作系统支持的实际值,并且可能旨在用作说“好吧,我们知道它至少可以是这个大的”。在为exec 设置参数时,这可能已经足够了,但我不会依赖该值来确定操作系统实际上可以传递程序的参数大小。
【解决方案2】:

不,ISO C99 标准没有限制。如果您使用的是“祝福”main 表单(其中有两个):

int main (int argc, char *argv[]);

那么您将被限制为有符号整数的最大大小(取决于实现,但保证至少为 215-1 或 32,767)。

当然,您甚至可以拥有更多,因为该标准特别允许非祝福的main 表单(例如,以long 为计数的表单)。

标准规定了参数的存储方式,argv[argc] 之类的东西必须为 NULL,但它并没有直接限制数量。

当然,在实践中会有一个限制,但这完全取决于实施和环境。但是,如果你不得不问,那么你可能正在做something wrong

大多数工具会将大量参数放入响应文件(例如 args.txt),然后传递单个参数,例如:

my_prog @args.txt

它绕过了参数数量和大小的任意限制。

【讨论】:

  • “非祝福”是指标准允许实现在没有操作系统的情况下“工作”吗?
  • 不,不完全是。即使没有传入参数,您仍然可以在非操作系统环境中使用两种规范形式之一。main 通常不是起点,因此启动代码可能会推送零 argc 和 NULL @987654331 @ 在调用main 之前。我的意思是 ISO 允许 main 的其他变体,例如来自 UNIX 的 {argc, argv, envp} 变体,其中环境也被传入。
  • +1 用于提供一些 Windows 答案。 @pmg:不,这意味着标准允许操作系统/环境为main 定义其他不可移植的格式。
  • 嗯,好的。 ISO 允许 main 的变体,但“以其他实现定义的方式”,因此通过使用不同的 main 原型,您将自己锁定到特定的实现。
  • 是的,编译器至少必须提供两种规范形式。其他任何东西都是可选的并且是实现定义的,所以你是对的 - 你可能会将自己绑定到那个实现(或兼容的)。
【解决方案3】:

我不这么认为。虽然可能没有理论上的限制,但计算机可能无法处理 150 万个参数。你有什么特别的理由需要知道这一点吗?我不建议对选项、文件参数等以外的东西使用命令行参数...

【讨论】:

  • 正是因为这次讨论,我与我的一位同事进行了讨论。我的同事在一次采访中被问到这个问题。我想知道它是否会受到堆栈大小或 int 大小的限制,正如安德鲁提到的那样,但我不确定其中的任何一个。
  • @Ravi:他们不会进入堆栈。它更有可能受到进程内存布局或其他操作系统配置的限制。理论上,您可以实现一个 新的 C 环境,而不是具有更多功能的原生平台 ABI。
  • @Potatoswatter:参数空间通常分配在进程的初始堆栈上。将它们放在那里很容易,因为无论如何操作系统都必须设置这个区域,并且它确实允许参数的大小在操作系统的未来版本中变化或增长,因为它不依赖于参数的大小。
【解决方案4】:

C 本身没有明确的限制。这是未在语言中定义而是在实现中定义的行为示例。请记住,语言本身与其实现、后续库、IDE 等不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-20
    • 1970-01-01
    • 2013-09-21
    • 2011-05-09
    相关资源
    最近更新 更多