为啥要检查 (*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:是的,*argv
与 argv[0]
相同。当您从普通 shell 运行应用程序时,这通常是不可能的。但我认为如果您通过使用exec
系统调用并手动传递数组直接从另一个程序执行进程,则可能是可能的。
@Shaun:嗯,将程序名称放在argv
中并不神奇。 Shell 在生成您的进程时将其放入数组中。可能(取决于平台)手动制作一个不将此类参数传递给您的程序的启动器进程。
@Shaun:也许你的教授……错了?
@Shaun,程序可能增加了argv
,所以它现在指向一个空指针。请参阅@Steve 的回答。
@Shaun:可以肯定地假设在正常情况下是这种情况。但是既然argc
是专门用来计算参数数量的,你为什么要冒险不这样做呢?添加检查argc
的if
语句并不是什么大问题。以上是关于为啥要检查 (*argv == NULL)? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥 main(int argc, char* argv[]) 需要两个参数? [复制]
为啥 Eclipse 生成的 equals() 实现会在类型检查(instanceof)之前检查 null?
为啥使用 null 函数而不是 == [] 来检查 Haskell 中的空列表?