C中数组和字符串的混淆
Confusion About Array and String in C
S1
、S2
和S3
有什么区别?
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
。
说明S2
和S3
相同,S1
和S2
不同。
为什么会这样??
为什么这三个不是等价的?
当我将 '[=11=]'
添加回 S1b
、S1c
时。所有3个都是一样的。这是可以理解的。
但是为什么在我的第一次试用中,S2
和 S3
是一样的??我也没有包括 '[=11=]'
。我怀疑 S1
和 S2
应该相同,但 S2
和 S3
不一样。
谁能告诉我为什么我的想法是错误的???
感谢您的回答。我已尝试将设置更改为以下内容:
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";
现在很明显 S2
和 S3
不一样,因为它们相差 '[=11=]'
。
但是,我还是有点疑惑,为什么我用strcmp来比较,这次S1
和S2
又不一样了?
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
比较数组的实际内存值:
- S1 有 6 个元素大,但您只指定 0-5 的值,第 6 个元素未明确设置,因此它保留内存位置在分配之前的任何值。
- S2 类似于 S1 ,只提供了 5 个元素,但是当使用
{,}
语法时,任何额外的元素都会被清零。所以 char foo[5] = { 1, 2 }
等同于 char foo[5] = { 1, 2, 0, 0, 0}
.
- 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
等赋值时应牢记这一点
S1
、S2
和S3
有什么区别?
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
。
说明S2
和S3
相同,S1
和S2
不同。
为什么会这样??
为什么这三个不是等价的?
当我将 '[=11=]'
添加回 S1b
、S1c
时。所有3个都是一样的。这是可以理解的。
但是为什么在我的第一次试用中,S2
和 S3
是一样的??我也没有包括 '[=11=]'
。我怀疑 S1
和 S2
应该相同,但 S2
和 S3
不一样。
谁能告诉我为什么我的想法是错误的???
感谢您的回答。我已尝试将设置更改为以下内容:
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";
现在很明显 S2
和 S3
不一样,因为它们相差 '[=11=]'
。
但是,我还是有点疑惑,为什么我用strcmp来比较,这次S1
和S2
又不一样了?
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
比较数组的实际内存值:
- S1 有 6 个元素大,但您只指定 0-5 的值,第 6 个元素未明确设置,因此它保留内存位置在分配之前的任何值。
- S2 类似于 S1 ,只提供了 5 个元素,但是当使用
{,}
语法时,任何额外的元素都会被清零。所以char foo[5] = { 1, 2 }
等同于char foo[5] = { 1, 2, 0, 0, 0}
. - 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