C 字符指针长度

C char pointer length

这是 Coursera 上的测验(未评分)。问题是,以下代码可能计算出什么?正确答案是 127 和 0(其他选项是 crash、-1、128。为什么下面的代码可能计算为 0?我明白为什么它会计算为 127。它是否就像 char 字节未初始化一样简单,因此随机的?它也可以评估为 0 到 127 之间的任何#吗?

int foo(void) {

    char bar[128];

    char *baz = &bar[0];

    baz[127] = 0;

    return strlen(baz);

}

代码的行为是不确定的。我的意思是答案可以是 0 到 127 之间的任何值。

strlen 将读取未初始化的内存,但不包括 bar[127] 作为终止条件。

但是因为该数组由 char 个元素组成,读取这些数据不是 undefined 因为 char 类型不能有 trap代表性。只是它们包含 不确定 值。

(如果 bar 具有静态存储持续时间,那将是完全不同的事情。那么答案将始终为零)。


下面的大部分评论都是针对此答案的错误表述做出的反应,该表述指出行为未定义。

之前这个答案有错误的信息,这个案例没有调用 undefined behavior.


编辑后的答案:

TL;DR 我们无法得到明确的答案,代码包含不确定的行为。

具体来说,char bar[128]; 是一个自动局部变量,如果未明确初始化,将包含 不确定 个值。

引用 C11,章节 §6.7.9

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. [....]

在您的代码中,您只为索引 127 处的一个数组成员赋值。其余元素的值仍然不确定。

尝试将该数组(基本上是指向数组第一个元素的指针)传递给 strlen(),导致读取这些值( 搜索 null-terminator ) 并且由于不确定的值,无法保证它会在任何 特定 位置找到 null-terminator。

  • 它可以很好地找到第一个元素中的空终止符(ASCII 值 0)和 return 0。
  • 它也无法在任何其他数组元素中找到任何空终止符(ASCII 值 0),直到最后一个和 return 127.
  • 它可以在数组中的任何位置找到空终止符,return 算。

所以,这个问题没有确定的答案。


注:(弥补我错误的理解,防止读者跌倒进一步陷入同一个陷阱)

这里,读取未初始化的值(即不确定的值)不会像人们想象的那样调用未定义的行为。

一行:对象取地址

这个话题有详细的讨论,参考here

如所列 here,有两件事可能会使此代码成为 UB。这是一个自动存储时间的变量,它的地址已被占用,所以第一种情况肯定不适用。

根据陷阱表示的定义,变量也不允许包含陷阱表示 C11 6.2.6.1/5 强调我的:

Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined.50) Such a representation is called a trap representation.

这意味着该数组包含未指定的值。这种未指定值的一种情况可能是数组中任何位置的值 0,被视为空终止符。