列表初始化的char数组是否仍为空终止?

时间:2016-06-21 21:58:40

标签: c++ pointers char

当我通过Lippman C ++ Primer(第5版,C ++ 11)时,我遇到了这段代码:

char ca[] = {'C', '+', '+'};  //not null terminated
cout << strlen(ca) << endl;  //disaster: ca isn't null terminated

在ca上调用库strlen函数(不是以null结尾)会导致未定义的行为。 Lippman等人说&#34;这个调用的最可能的影响是strlen将继续查看跟随ca的内存,直到遇到空字符。&#34;

稍后的练习将询问以下代码的作用:

const char ca[] = {'h','e','l','l','o'};
const char *cp = ca;
while (*cp) {
   cout << *cp << endl;
   ++cp;
}

我的分析:ca是一个非空终止的char数组。 cp,一个指向char的指针,最初保存ca [0]的地址。 while循环解除引用指针cp的条件,将生成的char值上下文转换为bool,并仅在转换结果为true时执行循环块。&#39;由于任何非null char都转换为bool值为&#39; true,&#39;循环块执行,将指针增加char的大小。然后循环遍历内存,打印每个char,直到到达空字符。因为ca不是以空值终止的,所以循环可以继续远远超过ca [4]的地址,将后来的内存地址的内容解释为字符并将它们的值写入cout,直到碰巧遇到发生的一大块位表示空字符(全0&#39; s)。这种行为类似于Lippman等人提出的strlen(ca)在前面的例子中的作用。

但是,当我实际执行代码(再次使用g ++ -std = c ++ 11进行编译)时,程序会一直打印:

'h'
'e'
'l'
'l'
'o'

并终止。为什么呢?

2 个答案:

答案 0 :(得分:3)

最有可能的解释:在现代桌面/服务器操作系统(如Windows和Linux)上,内存在映射到程序的地址空间之前会被清零。因此,只要程序不将相邻的内存位置用于其他内容,它就会看起来像一个空终止的字符串。 在您的情况下,相邻的字节可能只是填充,因为大多数变量至少是4字节对齐。

就语言而言,这只是未定义行为的一种可能实现。

答案 1 :(得分:0)

  

列表初始化的char数组是否仍为空终止?

没有隐式的空终止符。

如果使用null-terminator初始化了至少一个字符,则list-initialized char数组包含以null结尾的字符串。

如果所有字符都不是空终止符,则该数组不包含以空字符结尾的字符串。

  

程序始终打印...并终止。为什么呢?

您分析了数组将被越界访问。你的分析是正确的。您还应该知道,访问数组越界有未定义的行为。因此,为什么它的行为与此的答案是:因为行为未定义。

正如我已经提到的,你的分析是正确的。只有你的(暗示)假设当访问超出范围的内存时,第一个值必须是非零值。这种假设是错误的,因为它不能保证。