我在C中写了以下代码。
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[4] = "abcd";
char str2[4] = "abcd";
printf("%d\n",strcmp(str1,str2));
return 0;
}
我期望返回值为0(因为我被教导strcmp函数对于相等的字符串返回0)。但它打印1!
Success time: 0 memory: 2248 signal:0
1
这是一个错误吗?或者我错过了什么?
答案 0 :(得分:9)
因为你的阵列不够长。您没有考虑字符串的零终结符。你的字符串需要5个字符,字符串本身需要4个字符,零终结符需要1个字符。
写:
char str1[5] = "abcd";
char str2[5] = "abcd";
BTW我想知道为什么你的编译器没有发出警告或者发出警告?
答案 1 :(得分:2)
你的一个字符串在记忆中看起来像这样:'a''b''c''d''\ 0'。也就是说,就像每个字符串一样,它由'\ 0'终止,这是一个像'a'或'b'的字符。因此,您需要五个字符的空间才能存储字符串“abcd”,并且必须通过char str1 [5]声明它。
答案 2 :(得分:2)
要么为数组提供正确的大小,要么让编译器为你做所有事情
char str1[] = "abcd";
char str2[] = "abcd";
在这种情况下,编译器将为您的字符串提供足够的空间。
答案 3 :(得分:2)
(Pascal Cuoq提供)
C99标准§6.7.8.¶14说
字符类型数组可以由字符串初始化 文字,可选择括在括号中。连续的人物 字符串文字(包括终止空字符if) 有空间或者如果数组的大小未知)初始化 数组的元素。
由于字符串由空字节'\0'
终止,因此字符串文字"abcd"
中的实际字符数为5
。数组str1
和str2
的大小为4
。因此,它们不能保存空字节,实际上不是字符串。以下陈述是等效的。
char str1[4] = "abcd";
char str1[4] = {"abcd"}
char str1[4] = {'a', 'b', 'c', 'd'};
将str1
和str2
传递给strcmp
会调用未定义的行为,因为它们不是字符串。 strcmp
将超出str1
和str2
指向的缓冲区,因为它无法找到终止空字节。这是未定义的行为,可能由于段错误而导致程序崩溃。
字符串是由空字节'\0'
终止的字符数组。因此,字符串文字"abcd"
的长度为5
而不是4
。请注意,标准库函数strlen
不计算空字节,因此在这种情况下,strlen("abcd")
会返回4
。
使用字符串文字初始化数组时,最好将数组大小留空,自动确定该数组大小足以存储初始化的字符串文字中的所有字符。
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[] = "abcd";
char str2[] = "abcd";
printf("%d\n", strcmp(str1, str2)); // prints 0
return 0;
}