C中数组和字符串的混淆

Confusion About Array and String in C

S1S2S3有什么区别?

char S1[6];
S1[0] = 'A';
S1[1] = 'r';
S1[2] = 'r';
S1[3] = 'a';
S1[4] = 'y';

char S2[6] = {'A','r','r','a','y'};

string S3 = "Array";

当我使用 if (strcmp(a,b) == 0) 运行程序时,其中 a, b = S1, S2, S3。 说明S2S3相同,S1S2不同。 为什么会这样?? 为什么这三个不是等价的?

当我将 '[=11=]' 添加回 S1bS1c 时。所有3个都是一样的。这是可以理解的。

但是为什么在我的第一次试用中,S2S3 是一样的??我也没有包括 '[=11=]'。我怀疑 S1S2 应该相同,但 S2S3 不一样。

谁能告诉我为什么我的想法是错误的???

感谢您的回答。我已尝试将设置更改为以下内容:

char S1[5];
S1[0] = 'A';
S1[1] = 'r';
S1[2] = 'r';
S1[3] = 'a';
S1[4] = 'y';

char S2[5] = {'A','r','r','a','y'};

string S3 = "Array";

现在很明显 S2S3 不一样,因为它们相差 '[=11=]'。 但是,我还是有点疑惑,为什么我用strcmp来比较,这次S1S2又不一样了?

It shows that S2 and S3 are the same, and S1 and S2 is different.

S3 包含 S1 没有的 nul 终止符。这个string S3 = "Array";表示

| A | r | r | a | y | [=10=] |

而 S2 是

| A | r | r | a | y | [=10=] |

而 S1 是

| A | r | r | a | y | Garbage |

S1 和 S2 比较会导致 UB(我推测),因为 S1 不是以 nul 结尾的,并且我们在 strcmp.

中没有传递长度
#include <stdio.h>
#include <string.h>

int main(void) 
{
    char S1[6];
    S1[0] = 'A';
    S1[1] = 'r';
    S1[2] = 'r';
    S1[3] = 'a';
    S1[4] = 'y';
    S1[5] = 0;

    char S2[6] = {'A','r','r','a','y', 0};
    printf("%d" ,strcmp(S1,S2));
    return 0;
}

输出:

0

比较数组的实际内存值:

  1. S1 有 6 个元素大,但您只指定 0-5 的值,第 6 个元素未明确设置,因此它保留内存位置在分配之前的任何值。
  2. S2 类似于 S1 ,只提供了 5 个元素,但是当使用 {,} 语法时,任何额外的元素都会被清零。所以 char foo[5] = { 1, 2 } 等同于 char foo[5] = { 1, 2, 0, 0, 0}.
  3. S3 使用字符串语法方式初始化数组,创建一个 char(或 wchar_t)的数组,并将额外元素设置为 [=16=](空终止符) .

视觉上:

S1 = 0x41, 0x72, 0x72, 0x61, 0x79, 0x??
S2 = 0x41, 0x72, 0x72, 0x61, 0x79, 0x00
S3 = 0x41, 0x72, 0x72, 0x61, 0x79, 0x00

请注意,您 运行 遇到了 strcmp 的安全问题:它没有长度参数,它会一直搜索直到遇到 [=16=],这可能永不(即直到它导致段错误或访问冲突)。而是使用更安全的函数,例如 strncmp 或(如果使用 C++)std::string 类型。

strcmp() 函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续执行以下对,直到字符不同或到达终止空字符为止。

我认为使用它来比较 S1 和 S2 是不安全的。 strcmp 的输入是第一个字符的地址。 S1 不是空终止的。虽然在这两种情况下都分配了 6 个字节,但 S1[5] 没有被初始化。很可能他们有一些垃圾价值。这里的风险是 strcmp 最终也会在搜索字符差异或空字符时比较未分配的内存。这甚至会导致段错误或访问冲突。

可视化 S1、S2、S3 的内存对齐可能是这样的

S1 = A | r | r | a | y | ?
S2 = A | r | r | a | y | 0
S3 = A | r | r | a | y | 0

S2 和 S3 之间的任何比较都是安全的。 S1 vs S2 或 S3 可能不是。

只是添加到现有答案中

char S2[6] = {'A','r','r','a','y'};

string S3 = "Array";

两者都是 NULL 终止的,因此 strcmp() 工作得很好并且说它们是相同的。虽然对于 S1 分配是显式完成的,但该数组没有 NULL 终止。所以这不是 C 中的有效字符串。因此使用 strcmp() 可能会导致未定义的行为。

S3 的重点是 S3 是一个只读的字符串文字。这些类型的值大多存储在只读位置。因此,当您尝试在初始化后向 S3 写入内容时,您可能会看到 crash.So 我们在使用 S3

等赋值时应牢记这一点