特别是,以下定义明确,还是表现出未定义的行为?
memcmp(0, 0, 0);
这在C和C ++之间有区别吗?理想情况下,请提供标准报价。
答案 0 :(得分:31)
特别是,以下定义明确,还是表现出未定义的行为?
未定义。 C99 7.21.1 / 2说明了所有字符串函数:
除非明确说明 否则在本子条款中的特定函数的描述中,指针参数 在这样的电话上仍然应该有有效值
并且7.21.4.1中memcmp
的描述没有明确说明。
这在C和C ++之间有区别吗?
不,C ++对C库函数的定义遵循C语言,对memcmp
没有什么特别的说法。
答案 1 :(得分:3)
令人惊讶的是,尽管这似乎是标准中一个明显错误的情况-忽略了零长度memcmp很好(并且始终返回0)的原因-大量的理论用来解释为什么这样做被标记为“未定义的行为”。上面接受的答案是一个很好的例子,以后的讨论here也是如此。
不幸的是,在memcmp(0,0,0)
未定义的理论得到支持之后,Gcc决定通过在memcmp中添加__nonull属性来强烈执行这一不幸的决定,从而导致可能错误的优化和UBSAN警告。只有到那时,这个调用才真正变得未定义:-(
但是,如果我们从逻辑上看,memcmp(0, 0, 0)
是定义明确的,并且应始终返回0(等于):Posix中memcmp()
的功能描述为:
memcmp()函数应将s1指向的对象的前n个字节(每个解释为无符号字符)与s2指向的对象的前n个字节进行比较。
当n = 0时,这意味着将不比较任何字节。如果不比较任何字节,则不应取消引用任何指针,并且该指针是什么都没有关系。这应该很明显,而且C标准忘了提及它的事实不过是标准中的一个错误。
有趣的是,Linux memcmp(3)和FreeBSD memcmp(3)手册页与gcc意见不一致,并宣称应应允许这种情况:
Linux手册页显示:
如果n为零,则返回值为零。
BSD会说:
零长字符串始终相同。