C 相等运算符是否比较两个字符串的字面值或它们的内存位置?

Does the C equality operator compare the literal value of two strings or their memory locations?

我无法理解 == 运算符的这种行为:

char s1[4];
s1[0] = 'a';
s1[1] = 'a';
s1[2] = 'a';
s1[3] = '[=10=]';

char *s2 = "aaa";
char *s3 = "aaa";

printf("s1: %s\n", s1); // aaa
printf("s2: %s\n", s2); // aaa
printf("s3: %s\n", s3); // aaa
printf("s1 == s2: %d\n", (s1 == s2)); // 0
printf("s1 == s3: %d\n", (s1 == s3)); // 0
printf("s2 == s3: %d\n", (s2 == s3)); // 1

3个字符串的字面值都是一样的(aaa),为什么只有s2s3比对成功,s1比对不成功s2?显然它们都有不同的内存位置,因此无法解释结果。

谢谢

这将比较指针的值。换句话说,内存位置。

比较字符串的正确方法是使用库函数 strcmp:

  if(strcmp(s1, s2) == 0) { printf("The strings are the same."); }

您的代码的风险之一是您已将指针设置为静态字符串。即使您将它们编写为两个单独的字符串,编译器也可以轻松地将其优化为单个字符串。这会给你两个指向相同内存位置的指针,这将使它们看起来相等,即使它们应该在你的逻辑中是不同的字符串。

比较是比较内存地址,而不是字符串内容(使用 strcmp() fr)。但是

char *s2 = "aaa";

创建一个只读字符串。它不是 const char * 以避免破坏旧代码/.

char s1[] = "aaa";

char s1[4]; /* etc, initialise by hand */

在读/写内存中创建一个字符串。所以在第一种情况下,编译器意识到它可以合并两个相同的字符串。

在表达式中,数组指示符被隐式转换为指向其第一个元素的指针。

来自 C 标准(6.3.2.1 左值、数组和函数指示符)

3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

字符串文字具有字符数组类型。来自 C 标准(6.4.5 字符串文字)

6 In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals.78) The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. For character string literals, the array elements have type char, and are initialized with the individual bytes of the multibyte character sequence...

例如在这个表达式中

s2 == s3

有两个字符串文字的第一个字符的比较地址。

另外如果要写的话

"aaa" == "aaa"

然后表达式可以生成 1 或 0,具体取决于编译器选项,因为根据 C 标准(6.4.5 字符串文字)

7 It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.

如果您想将字符串文字作为数组进行比较,而不是比较它们第一个字符的地址,您应该使用在 header <string.h>[=18= 中声明的标准 C 函数 strcmp ]

例如

#include <string.h>

//...

printf("s1 == s2: %d\n", strcmp( s1, s2 ) == 0 ); 

The literal value of all 3 strings is the same

否 - 没有 3 个 字符串

s1是一个数组,其内容构成一个字符串

s2, s3 是指针。在这种情况下,这 2 个指针恰好被初始化为相同的值。该值是 字符串文字 "aaa".

地址

只有 2 个 字符串 :一个在数组 s1 中,另一个是 字符串文字 "aaa"存在于内存中的某个地方。


当在 s2 == s3 中将指针与指针进行比较时,比较的是这 2 个地址,而不是指向的内容。它们在这里是相等的,因为在 1 "aaa" 上对要初始化的两个指针进行了编译优化。

当数组与指针比较时,如 s1 == s2,数组 s1 被转换为其第一个元素 &s1[0] 的地址,并且该地址与指针 s2。比较是错误的,因为数组和 字符串文字 存在于不同的内存位置。