【问题标题】:String with 3 characters shows unexpected output while String with 6 characters shows correct output3 个字符的字符串显示意外输出,而 6 个字符的字符串显示正确的输出
【发布时间】:2025-11-27 08:00:01
【问题描述】:

这是我的 C 代码

#include <stdio.h>

int main()
{
    char c[3] = "abc";
    char a[6] = "Shamal";

    printf("%s\n\n", c);
    printf("%s\n\n", a);

    return 0;
}

这里的输出是

abcW?

Shamal

6 个字符的字符串正确显示字符串,而 3 个字符的字符串显示 W?在代码的末尾。

我知道我们需要输入空字符 '\0' 来终止字符串。但是这里两个字符串都没有空字符,但只有一个可以正常工作。这是什么原因?

【问题讨论】:

  • 原因是未定义的行为未定义的。或者换一种说法,没有理由,就是这样。
  • 编译所有警告和调试信息 (gcc -Wall -Wextra -g)
  • ca 不是 字符串(没有 nul-terminating 字符),它们是 字符数组。如果您声明为,例如char c[] = "abc";(或char c[4] = "abc";),那么编译器将根据您的字符串初始化在末尾包含一个nul-terminating字符。您没有提供足够的空间(短 1 个字符)来创建字符串。 (P.S. nul-terninating 字符只是十进制 0 或字符 '\0' -- 它们是等价的)
  • 只是为了添加一些不请自来的迂腐,根据标准应该是int main(void)

标签: c string


【解决方案1】:

正如上面的评论所说,未定义是未定义的,但您的问题的确切答案是,第一个字符串之后的内存字节不是 0,而是 'W' 然后是 '?之后是 0,它终止一个字符串。

对于第二个字符串,恰好字符串后面的一个字节意外为0,因此打印正确。

尝试重新排序初始化并查看输出是否更改(很可能会更改)。

【讨论】:

    【解决方案2】:

    每当您编写char c[4] = "abc";char c[] = "abc"; 之类的内容时,字符串abc 都会存储在内存中(您无法更改此字符串),并会自动附加\0。在这两种情况下,您都没有为终止 NUL 字符分配空间。

    对于char a[6] = "Shamal";,如果您循环字符并按索引05 打印它们,您将得到您的字符串。

    现在,如果您仔细观察,您已经为六个字符留出了空间,而\0 没有空间。 \0 可能会被写入您不拥有的空间,即在 l 之后。在这个阶段,您已经超出了您认为足够的缓冲区空间。这本身就足以引起UB。当您要求printf 打印出您的字符串时,会出现另一个问题。 printf 继续打印,直到找到 \0。一旦你调用了 UB,就不知道会发生什么。

    查看this 以获得其他解释。

    【讨论】:

      【解决方案3】:

      继续我的评论,您根本没有提供足够的空间来在初始化中创建字符字符串。以下为 nul-terminating 字符创建 字符数组 没有空格:

      char c[3] = "abc";
      char a[6] = "Shamal";
      

      在编译期间您不会收到任何警告,因为初始化是对字符数组的有效初始化——而不是字符串

      例如,char c[3] = "abc";,会在内存中产生以下连续字节:

          | a | b | c |
      

      这是一个有效的 3 元素字符数组,每个元素都可以索引为 c[0], c[1], c[2]。但是,要将c 用作字符串c 需要以下内存中的4 个连续字节

          | a | b | c |\0|
      

      要更正此问题并允许编译器将 nul-terminating 字符作为初始化的一部分,请不要为数组提供大小,编译器将自动调整数组大小以提供包含 nul-character 所需的额外空间,例如

      char c[] = "abc";
      char a[] = "Shamal";
      

      或者(更容易出错),自己为 nul-character 提供空间,例如

      char c[4] = "abc";
      char a[7] = "Shamal";
      

      两者都将导致 ca 包含 nul-terminating 字符,允许在您的代码中将每个字符用作 字符串

      【讨论】: