我已经读过以下结果导致未定义的行为。
strcmp(foo, NULL);
但究竟发生了什么“在引擎盖下”,可以这么说? foo
与垃圾数据进行比较吗? NULL
被解除引用了吗?导致“未定义行为”的细节是什么?
答案 0 :(得分:14)
这取决于实现,可以自由地假设您的参数有效(即在这种情况下不为null)。从执行到执行,或者从一个实现/平台到另一个实现/平台,行为可能会也可能不会重现。
答案 1 :(得分:8)
C11在7.1.4“使用库函数”中非常清楚:
除非在详细说明中另有明确说明,否则以下每个陈述均适用 以下描述:如果函数的参数具有无效值(例如[...]空指针[...])[...],则行为未定义。
7.24.4中strcmp
的描述没有另外说明,因此行为确实未定义。
答案 2 :(得分:5)
这是glibc中strcmp的当前实现:
/* Compare S1 and S2, returning less than, equal to or
greater than zero if S1 is lexicographically less than,
equal to or greater than S2. */
int
strcmp (p1, p2)
const char *p1;
const char *p2;
{
const unsigned char *s1 = (const unsigned char *) p1;
const unsigned char *s2 = (const unsigned char *) p2;
unsigned char c1, c2;
do
{
c1 = (unsigned char) *s1++;
c2 = (unsigned char) *s2++;
if (c1 == '\0')
return c1 - c2;
}
while (c1 == c2);
return c1 - c2;
}
答案 3 :(得分:0)
你传递了两个指针,strcmp取消引用它们的内容并进行比较,直到遇到差异或空字符。失败发生在不同的抽象级别,strcmp本身就没有失败。许多系统在解除引用NULL指针时生成SIGSEGV符号,但这不是必需的。
请注意,ISO标准没有定义很多内容,因此将实现细节留给实现。在ISO C级别,您的示例没有任何问题,但结果不能保证是可预测的。 (除非你参考基础系统的规则,否则没有任何实际测试可以保证精确和可重复,除非他们另有说明。)
当我们谈论抽象级别时,我们不能问“如果”,因为规则很明确并且说“不要这样做,行为没有在这里定义”。