为啥要检查 (*argv == NULL)? [复制]

Posted

技术标签:

【中文标题】为啥要检查 (*argv == NULL)? [复制]【英文标题】:Why check if (*argv == NULL)? [duplicate]为什么要检查 (*argv == NULL)? [复制] 【发布时间】:2011-01-21 02:49:06 【问题描述】:

在我目前学习的数据结构课程中,我们的任务是用 C++ 编写一个网络爬虫。为了让我们领先一步,教授为我们提供了一个从给定 URL 获取源代码的程序和一个简单的 html 解析器来去除标签。该程序的主函数接受参数,因此使用 argc/argv。用于检查参数的代码如下:

// Process the arguments
if (!strcmp(option, "-h"))

    // do stuff...

else if (!strcmp(option, ""))

    // do stuff...

else if (!strcmp(option, "-t"))

    // do stuff...

else if (!strcmp(option, "-a"))

    // do stuff...


if ( *argv == NULL )

    exit(1);

其中“选项”已使用 argv[1] 中的开关填充,而 argv[2] 及更高版本具有剩余的参数。我理解的第一个块很好,如果开关等于字符串,则根据开关做任何事情。我想知道最后一个 if 块的目的是什么。

可能是我的 C++ 有点生疏,但我似乎记得 *argv 等同于 argv[0],基本上意味着它正在检查以确保参数存在。除了我的印象是 argv[0] 总是(至少在大多数实现中)包含正在运行的程序的名称。我突然想到,如果 argc 等于 0,则 argv[0] 可能为空,但在 Google 上搜索我找不到一个帖子来确定这是否可能。

所以我转向你。最后的 if 块检查到底是什么?

编辑: 我已经按照所选答案的 cmets 中提供的推理进行了处理,即可能故意导致 argv[0] 变为 NULL,或者基于其他方式变为 NULL main 的特定于平台的实现。

【问题讨论】:

注意argv 不是一个数组,而是一个指针。这意味着您完全可以说 argv++ 来遍历选项。您不必修改*argv 的值。 出于好奇,你问教授的原因是什么? 现在,5年后,恐怕我真的不记得了。我似乎隐约记得问我的助教,推理与接受答案的 cmets 相同(请参阅问题中的编辑),但我可能是在编造,只是记住了所有错误。 :P 我知道这已经很晚了,但请注意,您可以使用getopt() 轻松解析命令行选项。 不确定是否有必要将此标记为重复,因为在链接的“重复”之前 3 个月提出并回答了此问题。 (实际上是 7 年前的那个时候>_>) 【参考方案1】:

3.6.1/2:

如果 argc 不为零这些参数 应在 argv[0] 中提供 ...和 ​​argv[0] 应为指针 到 NTMBS 的初始字符 表示使用的名称 调用程序或“”。的价值 argc 应为非负数。价值 argv[argc] 的数量应为 0。

强调我的。 argc 只保证非负,而不是非零。

这是在主入口处。 //do stuff 也有可能修改了argv 的值,或者它指向的数组的内容。选项处理代码在处理它们时将值移出 argv 并不是完全闻所未闻的。因此,*argv == null 的测试可能是在删除或跳过选项之后测试是否还有任何命令行参数。您必须查看其余代码。

【讨论】:

【参考方案2】:

只是猜测。

如果你的教授指的是这个怎么办?

while(*++argv !=NULL)

    printf("%s\n",*argv);

【讨论】:

【参考方案3】:

请记住 C 语言的可移植性,它可能并不总是在 Windows 或 Unix 等标准平台上运行。也许它是您洗衣机内的一些微代码,在一些廉价的黑客环境中运行。因此,最好在取消引用之前确保指针不为空,这可能会导致问题。

即便如此,你是对的。 *argv 与 argv[0] 相同,并且 argv 应该由环境初始化,如果提供的话。

【讨论】:

'也许它是您洗衣机内的一些微代码' - 很好,现在我正在等待消息“抱歉,您必须将 'Adobe Flash' 更新到最新版本才能进入漂洗周期。”【参考方案4】:

argc 将为您提供传递的命令行参数的数量。您应该不需要检查argv 的内容,看看是否没有足够的参数。

if (argc <= 1)  // The first arg will be the executable name
   // print usage

【讨论】:

@Shaun:是的,*argvargv[0] 相同。当您从普通 shell 运行应用程序时,这通常是不可能的。但我认为如果您通过使用exec 系统调用并手动传递数组直接从另一个程序执行进程,则可能是可能的。 @Shaun:嗯,将程序名称放在argv 中并不神奇。 Shell 在生成您的进程时将其放入数组中。可能(取决于平台)手动制作一个不将此类参数传递给您的程序的启动器进程。 @Shaun:也许你的教授……错了? @Shaun,程序可能增加了argv,所以它现在指向一个空指针。请参阅@Steve 的回答。 @Shaun:可以肯定地假设在正常情况下是这种情况。但是既然argc 是专门用来计算参数数量的,你为什么要冒险不这样做呢?添加检查argcif 语句并不是什么大问题。

以上是关于为啥要检查 (*argv == NULL)? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 main(int argc, char* argv[]) 需要两个参数? [复制]

为啥 Eclipse 生成的 equals() 实现会在类型检查(instanceof)之前检查 null?

为啥使用 null 函数而不是 == [] 来检查 Haskell 中的空列表?

为啥在检查 null 的长度时我没有收到错误 [重复]

在C语言编程中,为啥要将指针变量在开始的时候赋值为NULL?

为啥 Theme.of(context) 告诉我在取消引用之前检查该值是不是为“null”?