【问题标题】:Printing strings and concept of null character in C在 C 中打印字符串和空字符的概念
【发布时间】:2019-01-09 11:20:08
【问题描述】:

在阅读有关打印字符串的信息时,我看到了一条语句 "printf 一个接一个地写入字符,直到遇到一个空字符。如果空字符丢失,printf 继续超过字符串直到最终在内存中找到一个空字符”。 所以我写了一些代码:

案例 1:

char arr[4] = { 'a', 'b', 'c' } ;

if (arr[3]== '\0')

printf ("%s",arr);

输出为abc

这是否意味着编译器已自动将'\0' 存储在arr[3]。因为按照说法,printf只有遇到'\0'才会终止。

案例 2:

char arr[3] = { 'a', 'b', 'c' } ;

if (arr[3]== '\0')

printf ("%s",arr);

虽然不存在数组块arr[3],但输出还是abc,那为什么不是错误呢? printf 也打印了abc 并停止了,这意味着它一定遇到了'\0'。那么这是否意味着编译器在arr[2] 之后创建一个额外的数组块来存储'\0'。如果是这样,那么数组大小必须增加到4 个字节(每个char 类型字符1 个字节)。但是执行语句printf ("%d",sizeof (arr));给了我输出3,表明数组大小没有增加,表明没有arr[3]。那么if (arr[3]== '\0')这个条件是怎么成真的呢?

案例 3:

char arr[3] = "abc";

if (arr[3]== '\0')

printf ("%s",arr);

现在它给了我一个错误,说 “数组索引 3 超出了结尾(包含 3 个元素)”。 那么为什么这与 case 2不一样>。这是否意味着声明:

char arr[3] = "abc";

char arr[3] = { 'a', 'b', 'c' } ; 不同。

【问题讨论】:

  • "[...] 那为什么不是错误?" 这是错误。只是 C 不需要编译器或运行时系统来检测错误。任何事情都有可能发生。
  • 那么不同编译器的答案是否会有所不同?
  • 同一个编译器的不同版本,不同的编译选项,或者只是多次运行同一个程序,它们甚至可能不同。没有保证,也没有期望的一致性。
  • 我现在明白了。看来我在这个话题上想得太多了。

标签: c arrays string initialization c-strings


【解决方案1】:

如果数组的大小大于您显式初始化的元素数量,则其余元素将被初始化为零。

所以你可以有例如

char arr[50] = { 'a' };

第一个元素 (arr[0]) 将被初始化为包含 'a',其余 49 个元素将全部为零。

另请注意,当您定义一个包含三个元素的数组(如问题中的后两个示例中)然后使用 arr[3]== '\0' 时,您的索引超出范围并拥有 undefined behavior

此外,不在数组中的内存内容是不确定的。你不能指望它有任何价值。

最后,

char arr[3] = "abc";

char arr[3] = { 'a', 'b', 'c' };

实际上是一样的,都创建了一个包含三个元素的数组,内容为'a''b''c'

【讨论】:

  • @Avi 字符'\0'是字符形式的八进制值0。它完全等于0。它也完全等于'\x00'
  • @Avi 为什么不呢? 0'\0' 完全一样。
  • 对不起,我明白了。他们都是一样的
  • @Avi 未定义行为未定义。
  • @Avi C 从未进行过任何类型的边界检查。越界会导致未定义的行为。只是不要这样做。
猜你喜欢
  • 1970-01-01
  • 2022-10-02
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
  • 2013-02-26
  • 2020-07-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多