strncmp(NULL, "foo", 0)是否定义良好?

22

如果第三个参数为零,将NULL指针作为strncmp的参数是安全的吗?例如,如下调用:

strncmp(NULL, "foo", 0);

1
编译器不会优化掉整个指令吗? - Sourav Ghosh
1
@SouravGhosh 也许我简化得太多了。我感兴趣的情况是当三个参数都是在运行时获取这些值的变量时。 - Marian
3
可能由于未定义行为,编译器会将其替换为对维斯特洛最精锐战士的召唤。 - Lightness Races in Orbit
2个回答

35

这是一种未定义的行为

C标准通常规定,不应向库函数传递无效指针。

引用《C11》第7.24.1章“字符串函数约定”(强调我的

对于一个函数,如果声明为size_t n类型并指定了数组长度,则在调用该函数时,n可以具有零值。 除非在本子句中某个特定函数的描述中明确说明,否则在此类调用上的指针参数仍然应具有有效值,如7.1.4所述。在此类调用上,定位字符的函数找不到出现,比较两个字符序列的函数返回零,而复制字符的函数会复制零个字符。

我没有看到在7.24.4.4,strncmp()函数中有任何特定提及(作为前述约束的例外)。


为了解释“无效指针”的上下文,引用§7.1.4/p1,“使用库函数”:
「如果函数的参数具有“无效值”(例如函数域外的值,或程序地址空间之外的指针,或“null pointer”,或对应参数未被const限定时指向不可修改存储的指针)或者类型(在提升后)与可变参数函数所期望的类型不符,则其行为是未定义的。[...]」
关于NULL,引用§7.19,<stddef.h>
NULL 扩展为实现定义的空指针常量;[...]」

9
是的,在这个上下文中它是7.1.4/1:“如果函数的参数具有无效值(例如函数定义域之外的值,或程序地址空间之外的指针,或空指针,或相应参数未带const限定符而指向不可修改存储的指针)”。 - Lightness Races in Orbit
3
翻译从英语到中文。只返回翻译后的文本:(为了明确起见,我认为需要在答案中添加这一点以便完成它) - Lightness Races in Orbit
1
@LightnessRacesinOrbit: 关于传递null的评论并不意味着没有库函数可以传递null,而是指除非另有说明(例如在“free”的文档中),否则不能将null传递给库函数供其实际使用的指针,并且从指针复制零字节不符合大多数“使用”定义。我将超级激进的优化器包括在“故意模糊实现”中,因为强制程序员包含额外的检查,而优化器很可能无法消除这些检查,这是一种虚假的“优化”。 - supercat
3
C89标准是在编译器写手没有被命令实现有用的行为的时代编写的(这一事实表明,在标准被编写之前的十多年里,编译器写手一直在实现有用的行为)。标准的作者希望避免强制规定,这些规定可能会阻止符合标准的平台上的编译器生成与平台上已有的编译器一样高效的代码,这意味着如果另一种选择会增加成本,他们会使很多东西成为未定义行为。 - supercat
2
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - supercat
显示剩余12条评论

7

17
http://cppreference.com不是“官方”文档,而是由爱好者编写的公共Wiki。鉴于[标签:语言律师]标签,我认为我们应该只将语言标准视为此问题的权威参考资料,其他任何内容不能作为权威参考。 - Nate Eldredge
3
@NateEldredge: 我没有说它是权威的,也不是“唯一”的文档(这是“cppreference.com上的文档”)。但做一些基本的研究将是一个好的开始。然后OP可以要求对他们已经看到的内容进行确认。现在有了标准和Sourav的精彩答案。我认为提醒人们“阅读文档”是有价值的。 - Lightness Races in Orbit
1
谢谢您的回答。实际上,我对Sourav提供的那种答案很感兴趣(以及您宝贵的评论)。我想找到针对这样可疑代码行的原因。 - Marian
@Marian:确实,Sourav的回答是你所需要的。但我再次要求你在未来考虑从阅读文档开始进行研究。 - Lightness Races in Orbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接