You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何argc与argv在main函数外仍能正常工作?

为什么argc和argv在main函数外的函数中也能正常工作?

我意外发现argc和argv在main函数外的函数里也能正常输出命令行参数,以下是复现代码(使用GCC编译):

main.c

#include <stdio.h>

int test(void);

int main(void)
{
    test();
}

test.c

#include <stdio.h>

int test(int argc, char **argv)
{
    printf("argc = %i\n", argc);
    printf("args:\n");
    for (int i = 0; i < argc; i++)
    {
        printf("- %s\n", argv[i]);
    }
    printf("test called\n");
    return 0;
}

这本质是未定义行为,只是在GCC的x86/x86_64调用约定下碰巧“正常工作”了,并非标准C允许的行为。

具体原因:

  • 在x86_64 System V调用约定(GCC在Linux、macOS等系统默认使用的规则)中,函数的前几个参数通过寄存器传递:rdi存储第一个参数,rsi存储第二个参数。
  • main函数启动时,操作系统会把argc放入rdi寄存器,argv放入rsi寄存器。
  • 调用test()时没有传递任何参数,这些寄存器的值刚好保留了main启动时的初始值,因此test函数读取rdi和rsi时,就拿到了argc和argv的值。

但这完全是巧合,不具备通用性:

  • 如果在调用test()之前调用了其他函数,那些函数可能会修改rdi/rsi寄存器,test就会拿到错误的值。
  • 换用其他调用约定(比如Windows下的MSVC调用约定)或编译器(比如Clang在特定优化级别下),这个现象大概率会消失,甚至程序会崩溃。
  • 标准C明确规定,调用函数时参数的数量和类型必须与声明匹配,否则属于未定义行为,编译器可以做出任何处理,包括看似“正常工作”的情况。

内容的提问来源于stack exchange,提问作者t2a

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 09:55:02