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,被视为空终止符。
这是 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,被视为空终止符。