11、写出下面的结果
char str1[] = “abc”;
char str2[] = “abc”;
const char str3[] = “abc”;
const char str4[] = “abc”;
const char *str5 = “abc”;
const char *str6 = “abc”;
char *str7 = “abc”;
char *str8 = “abc”;
cout << ( str1 == str2 ) << endl;
cout << ( str3 == str4 ) << endl;
cout << ( str5 == str6 ) << endl;
cout << ( str7 == str8 ) << endl;
结果是:0 0 1 1
解答:str1,str2,str3,str4 是数组变量,它们有各自的内存空间;
而str5,str6,str7,str8 是指针,它们指向相同的常量区域。
在你提供的代码片段中,涉及到字符串数组和字符串指针的比较。在 C++ 中,使用 ==
运算符比较字符串(或字符数组)时,实际上比较的是指针的地址,而不是字符串的内容。这是导致结果不同的关键。
代码分析
#include <iostream>
using namespace std;
int main() {
char str1[] = "abc"; // 字符数组,存储在不同的内存地址
char str2[] = "abc"; // 字符数组,存储在不同的内存地址
const char str3[] = "abc"; // 常量字符数组,存储在不同的内存地址
const char str4[] = "abc"; // 常量字符数组,存储在不同的内存地址
const char *str5 = "abc"; // 指向字符串常量的指针
const char *str6 = "abc"; // 指向字符串常量的指针
char *str7 = "abc"; // 指向字符串常量的指针(不推荐,因字符串常量是只读的)
char *str8 = "abc"; // 指向字符串常量的指针(同上)
cout << (str1 == str2) << endl; // 0
cout << (str3 == str4) << endl; // 0
cout << (str5 == str6) << endl; // 1
cout << (str7 == str8) << endl; // 1
return 0;
}
逐行分析
-
str1 == str2
:str1
和str2
都是字符数组,存储在不同的内存地址上。因此,比较它们的地址会返回false
,即0
。
-
str3 == str4
:str3
和str4
也是字符数组,同样存储在不同的内存地址上,因此比较它们的地址也返回false
,即0
。
-
str5 == str6
:str5
和str6
是指向字符串常量的指针。在某些编译器或优化情况下,字符串常量"abc"
可能会存储在同一内存地址(常量池中)。因此,它们指向同一个内存地址,比较返回true
,即1
。
-
str7 == str8
:str7
和str8
也是指向字符串常量的指针。由于它们都指向相同的字符串常量"abc"
,因此同样返回true
,即1
。
总结
- 数组 vs. 指针:在 C/C++ 中,字符数组是不同的对象,比较时会比较它们的地址;而指向常量字符串的指针如果指向同一个字符串常量,则它们的地址是相同的。
- 输出结果:
0
(对于str1 == str2
)0
(对于str3 == str4
)1
(对于str5 == str6
)1
(对于str7 == str8
)
因此,最终的输出是:
0
0
1
1
注意事项
- 使用
char *
指向字符串常量是危险的,因为字符串常量通常是只读的,修改它们可能导致未定义的行为。建议使用const char *
来指向字符串常量。
字符数组和字符串常量在 C/C++ 中有明显的区别,这些区别涉及到内存分配、可修改性以及使用方式。下面是它们的详细对比和区分方法。
1. 定义和内存分配
-
字符数组:
- 使用数组定义,可以直接修改其内容。
- 在栈上分配内存,内存是可写的。
- 示例:
char str1[] = "abc"; // 创建一个字符数组,内容是 'a', 'b', 'c', '\0'
-
字符串常量:
- 通常是使用字符串字面值(如
"abc"
)创建的,存储在只读区域(常量区)。 - 不能修改其内容,尝试修改会导致未定义行为。
- 示例:
const char *str2 = "abc"; // str2 是指向字符串常量的指针
- 通常是使用字符串字面值(如
2. 可修改性
-
字符数组:
- 可以直接修改数组中的字符。例如:
char str1[] = "abc"; str1[0] = 'A'; // 合法,str1 变为 "Abc"
- 可以直接修改数组中的字符。例如:
-
字符串常量:
- 不可以修改,尝试修改会导致运行时错误:
const char *str2 = "abc"; // str2[0] = 'A'; // 错误,未定义行为
- 不可以修改,尝试修改会导致运行时错误:
3. 内存地址
-
字符数组:
- 每个字符数组在栈上有自己的内存地址。
- 即使内容相同,它们的地址也不同。
- 示例:
char str1[] = "abc"; char str2[] = "abc"; cout << &str1 << endl; // 地址不同 cout << &str2 << endl; // 地址不同
-
字符串常量:
- 同样的字符串常量在程序中可能只占用一个内存地址,多个指针可能指向同一个字符串常量。
- 示例:
const char *str3 = "abc"; const char *str4 = "abc"; cout << (str3 == str4) << endl; // 可能输出 1,表示地址相同
4. 使用场景
-
字符数组:
- 当需要修改字符串内容时,使用字符数组。
- 适合在需要动态修改字符的场合。
-
字符串常量:
- 当只需要读取字符串,且不需要修改时,使用字符串常量。
- 常用于定义常量字符串和在函数中传递字符串参数。
总结
- 字符数组是一个可修改的、存储在可写内存的数组,而字符串常量是不可修改的、存储在只读内存的常量。选择使用哪种取决于你对字符串的操作需求。理解这两者之间的区别能够帮助避免内存错误和程序崩溃。