C中的命令行参数,无法理解其行为

Posted

技术标签:

【中文标题】C中的命令行参数,无法理解其行为【英文标题】:Command line arguments in C, cant understand its behaviour 【发布时间】:2016-02-19 05:45:32 【问题描述】:

我有以下代码:

#include <stdio.h>
int main(int argc, char* argv[])
    int a = argv[1]?atoi(argv[1]):10;
    int b = argv[2]?atoi(argv[2]):20;
    printf("a = %d, b = %d\n", a, b);
    return 0;

如果我不提供任何命令行输入,“a”和“b”中的值 应该分别为 10 和 20,但实际上“a”的值为 10,而“b”的值为 0。 我不明白为什么会这样,因为我做的完全一样 在这两种情况下。

谢谢。

【问题讨论】:

因为您正在调用未定义的行为。如果未提供命令行参数,则代码不得访问那些 arg 条目。在这种情况下,不能保证它们都为 NULL。只有 argv[argc] 被 C 标准定义为 NULL。 在第三和第四行,尝试将argv[1]argv[2]更改为(argc&gt;1)(argc&gt;2) 我尝试检查 argv[1] 和 argv[2] 是否为空,结果 argv[2] 不为空,即使我没有在命令行上提供任何输入。谢谢。 【参考方案1】:

运行时(通常通过crt0 和kernel)保证(根据C99 或POSIX 标准)(对于main 的参数argcargv):

argc 为正

argv 是一个有效的非 NULL 指针,指向 argc+1 指针数组

argv[argc]NULL 指针

对于包含在 0 和 argc-1 之间的每个 iargv[i] 是一个(有效的非 NULL)指针,指向一个以零结尾的字符串

因此使用j&gt;argc(或j&lt;0)访问argv[j]undefined behavior (UB) - 所以只有通过深入了解实现细节才能解释发生的事情......

有效的argv[i] 不是pointer aliases,所以如果ij 都在0 和argc-1 之间,并且i != j, argv[i] ! = argv[j]

因此,您的代码在argc==1 时是错误的,因为访问argv[2] 是被禁止的(UB)。

你应该编码:

int main(int argc, char* argv[])
    int a = (argc>1)?atoi(argv[1]):10;
    int b = (argc>2)?atoi(argv[2]):20;

非常 scared 的未定义行为(另请参阅参考资料 here)。遗憾的是,带有 UB 的程序可能有时似乎“工作”(可能不会崩溃)。但在其他时候,坏事可能会发生。所以你应该想象最坏的情况。

【讨论】:

【参考方案2】:

如果我不提供任何命令行输入,“a”和“b”中的值 应该分别是 10 和 20。

不,如果您不提供任何命令行输入,您访问的将超出argv 数组的末尾,并且任何事情都可能发生(包括您的程序崩溃和烧毁)。

你的支票应该是:

int a = argc > 1 ? atoi(argv[1]) : 10;
int b = argc > 2 ? atoi(argv[2]) : 20;

这就是argc 的用途,告诉您argv 中有多少条目可供您访问。

【讨论】:

以上是关于C中的命令行参数,无法理解其行为的主要内容,如果未能解决你的问题,请参考以下文章

修改命令行构建参数

Java 的命令行 编译和运行参数 如:-cp 怎么理解?

命令行参数是啥?

如何仅使用命令行参数读取唯一行?

C程序获取命令行参数

c语言中命令行参数argc,argv[ ]