【问题标题】:C string initializer doesn't include terminator?C字符串初始值设定项不包括终止符?
【发布时间】:2010-10-03 01:41:33
【问题描述】:

我对下面的 C 代码 sn-ps 有点困惑:

printf("Peter string is %d bytes\n", sizeof("Peter")); // Peter string is 6 bytes

这告诉我,当 C 编译双引号中的字符串时,它会自动为空终止符添加一个额外的字节。

printf("Hello '%s'\n", "Peter");

printf 函数知道何时停止读取字符串“Peter”,因为它到达了空终止符,所以 ...

char myString[2][9] = {"123456789", "123456789" };
printf("myString: %s\n", myString[0]);

这里,printf 打印所有 18 个字符,因为没有空终止符(如果不去掉 9,它们将不适合)。 C 不是在变量定义中添加空终止符吗?

【问题讨论】:

    标签: c variables string


    【解决方案1】:

    你的字符串是 [2][9]。那些 [9] 是 ['1', '2', etc...'8', '9']。因为您在第一个数组维度中只给了 9 个字符的空间,并且因为您使用了全部 9 个字符,所以它没有空间放置 '\0' 字符。重新定义你的 char 数组:

    char string[2][10] = {"123456789", "123456789"};
    

    它应该可以工作。

    【讨论】:

      【解决方案2】:

      当然可以,只是没有为 '\0' 字节留出足够的空间。制作它:

      char string[2][10] = { "123456789", "123456789" };
      

      会如您所愿(仅打印 9 个字符)。

      【讨论】:

      • 编译器没有警告没有足够的空间容纳 0 字节是否有原因?如果我尝试添加另一个不适合的“9”,我会收到警告,但它似乎并不关心删除 0 字节?
      【解决方案3】:

      编译器没有警告没有足够的空间容纳 0 字节是否有原因?如果我尝试添加另一个不适合的“9”,我会收到警告,但它似乎并不关心删除 0 字节?

      【讨论】:

      • 在大多数情况下,C 假设您知道自己在做什么,并且当您说您想要填充的东西时,它相信这就是您的意思;但是,一旦您超出分配的空间,它就会知道您是白痴并警告您。
      • 假设您要存储 9 个字符。为什么 C 应该在最后为您包含一个空字节。空字节仅在该 char 数组用作字符串时才有用。
      • 编译器假设如果你想要足够的空间来容纳整个字符串,你已经完成了 char x[] = "abc";而不是 char x[3] = "abc";前者会自动且隐含地将其设为 char x[4]。
      【解决方案4】:

      '\0' 字节不是问题。大多数时候,如果你有这个:

      char code[9] = "123456789";
      

      下一个字节将离开变量的边缘,但将是未使用的内存,并且很可能为 0(除非您 malloc() 并且在使用它们之前不设置值)。所以大多数时候它是有效的,即使它对你不利。

      如果您使用 gcc,您可能还想使用 -Wall 标志,或其他(百万)警告标志之一。这可能会有所帮助(不确定)。

      【讨论】:

        【解决方案5】:

        如果你告诉 C 一个数组是给定的大小,C 不能使这个数组变得更大。如果它这样做,那就是不服从你!请记住,并非每个 char 数组都包含一个以空字符结尾的字符串。有时数组(如所使用的)确实是(单个)字符的数组。编译器不知道你在做什么,也无法读懂你的想法。

        这就是为什么 C 允许您初始化一个 char 数组,其中 null 终止符不适合,但其他一切都适合。用一个长一字节的字符串试试你的例子,编译器会抱怨。

        请注意,您的示例将编译,但不会按照您的预期进行,因为内容不是(以空结尾的)字符串。使用 GCC,运行您的示例,我看到了我应该看到的字符串,然后是垃圾。

        【讨论】:

          【解决方案6】:

          或者,您可以使用:

          char* myString[2] = {"123456789", "123456789" };
          

          像这样,初始化程序会为您的以空字符结尾的字符串计算正确的大小。

          【讨论】:

            【解决方案7】:

            C allows unterminated strings, C++ does not.

            C 允许字符数组 用字符串常量初始化。它 还允许字符串常量 初始化器恰好包含一个 比它的数组更多的字符 初始化,即隐式 的终止空字符 字符串可以被忽略。例如:

            char  name1[] =  "Harry";   // Array of 6 char
            
            char  name2[6] = "Harry";   // Array of 6 char
            
            char  name3[] =  { 'H', 'a', 'r', 'r', 'y', '\0' };
                                        // Same as 'name1' initialization
            
            char  name4[5] = "Harry";   // Array of 5 char, no null char 
            

            C++ 也允许字符数组 用字符串常量初始化,但是 总是包含终止的 null 初始化中的字符。因此 中的最后一个初始化程序(name4) 上面的例子在 C++ 中是无效的。

            【讨论】:

              猜你喜欢
              • 2016-07-25
              • 2011-01-03
              • 2019-04-16
              • 2018-09-26
              • 2015-09-20
              • 2020-07-31
              • 1970-01-01
              • 2010-09-08
              相关资源
              最近更新 更多