为什么即使我没有提供以空字符结尾的字符串,strcmp() 仍然返回 '0'?

3
在下面的代码中,我原本期望会出现一些奇怪的行为(比如无限循环),因为我没有提供以null结尾的字符串作为strcmp()函数的输入。
#include <stdio.h>

int main() 
{
  char string1[20];
  char string2[20] = {'H','e','l','l','o',};

  strcpy(string1, "Hello");
 // strcpy(string2, "Hellooo");
  printf("Return Value is : %d\n", strcmp( string1, string2));

  return 0;
}

输出结果如下:
 Return Value is : 0

为什么它显示两个字符串相等?

我猜测当我初始化数组(string2)时,其余的元素被填充为零。但由于该数组是局部的,这不应该是这种情况。


7
你的猜测是正确的。 - Bryan Chen
1
你说得对,数组的其余部分将被初始化为0。例如,初始化数组的常见方法是 char temp[100] = {0}。在这里,你只是提供了数组的第一个成员,但是如果你看一下 temp 的内存布局,你会发现整个数组已经填充了零。 - Abhineet
6个回答

6

如果对数组或结构体进行初始化时,只提供了部分数据,则数组或结构体的其余部分将被设置为0。这适用于string2


5
有一个例外情况:如果数组是从字符串字面值初始化的,则在空字符终止符后的字符是不确定的(参考C99 6.7.8#14;与仅适用于大括号包含列表的#21相比)。 - M.M

5

我删除了string2,然后得到了

72 101 108 108 111 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

余下的string2将填充0

for (i = 0; i < 20; i++)
    printf("%d ", string2[i]);

当我这样做时,我得到了:
char string2[20];

string2[0] = 'H';
string2[1] = 'e';
string2[2] = 'l';
string2[3] = 'l';
string2[4] = 'o';

72 101 108 108 111 127 0 0 -27 5 64 0 0 0 0 0 -1 -78 -16 0 Return Value is : 127

当您在定义部分初始化字符串时,其余的字符串将填充0

但是,当您只定义它然后为其分配值时,它将填充无用的值。


转储string2的值并查看尾随零表明,但并没有强烈证明char string2 [20] = {'H','e','l','l','o',};进行了零填充。还需要查看string2在定义之前的内存先前的值-这是一件棘手的事情。 - chux - Reinstate Monica

2

如已有人向您解释正确答案,这个例子就是要使其更加清晰易懂:

int main( int argc, char** argv )
{
 char temp[100] = {'A'} ;
 return 0 ;
}

数组初始化部分的反汇编代码如下:
//char temp[100] = {'A'} ;
// 41h is 'A', so this instruction fills the first index with 'A'
mov         byte ptr [ebp-6Ch],41h 
push        63h  
push        0    
lea         eax,[ebp-6Bh] 
push        eax 

// Then it calls memset which in turn fills the rest of array with zeroes.
call        @ILT+115(_memset) (0B11078h) 
add         esp,0Ch

2

部分初始化的数组将会被填充或初始化为剩余未初始化内存的零值

例如:

int a[10]={1,2,3}

剩余的索引将被填充(初始化)为零(0)。


1
无论string2数组的作用域是全局还是局部,它都将被初始化为零,在这种情况下。

唯一的区别是当您在本地声明string2并且根本不进行初始化时,即char string2[20];

以这种方式进行本地分配会在堆栈上分配string2,不会进行显式初始化,但如果您在全局范围内执行相同的操作,则该数组将被初始化为零(所有索引)。

因此,你的猜测部分正确!!


1
C11 (n1570), §7.24.2.3 strcpy函数
strcpy函数将s2指向的字符串(包括终止空字符)复制到s1指向的数组中。
你的string1和string2中前6个元素变得相同。终止符也在相同位置。

1
我认为问题是为什么string2也是以null结尾的。 - Robert
1
看来我误解了。他本可以使用char string1[20] = "Hello";而不是strcpy - cshu
注意:char string1 [20] =“Hello”; 不会像 char string2 [20] = {'H','e','l','l','o'}; 一样将 string1 [6]string1 [19] 初始化。 - chux - Reinstate Monica
@chux:是的,它们是不同的。但是,如果问题是“为什么string2以空字符结束”,那么区别就无关紧要了。 - cshu
@Griddoor 你说得对。 - chux - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接