问题描述:
C语言风格字符串3种定义方式有什么区别呢?
"hello"; // 底层就是字符数组 char s[] = "hello"; // 底层也是字符数组,会额外添加一个\0作为最后一个元素,当做结束标记 char *s2 = "hello";
问题解答:
在C语言中,字符串可以通过不同的方式定义,而每种方式在底层实现和使用上都有一些区别。下面是这三种定义方式的详细解释:
1. 直接使用字符串字面量
"hello"; // 字符串字面量
特点和用法:
- 这是一个字符串字面量,存储在只读的内存区域(通常是静态存储区或常量区)。
- 不能直接对其内容进行修改,因为尝试修改字符串字面量会导致未定义行为。
底层实现:
- 底层实际是一个字符数组,内容为
"hello"
,并且会自动在末尾添加一个\0
作为字符串结束标记。 - 编译器将其存储在只读内存中,因此它是不可变的。
2. 使用字符数组定义字符串
char s[] = "hello"; // 字符数组
特点和用法:
- 这是一个可修改的字符数组,定义时初始化为
"hello"
。 - 可以对
s
中的元素进行修改,因为它是一个普通的字符数组,存储在栈上或全局/静态区(如果是全局变量)。
底层实现:
- 底层是一个包含字符
h
,e
,l
,l
,o
,\0
的字符数组(总共 6 个元素)。 - 因为它是一个字符数组,整个数组的内容是可以修改的。
示例:
s[0] = 'H'; // 合法,可以修改字符数组的内容
3. 使用字符指针指向字符串字面量
char *s2 = "hello"; // 字符指针
特点和用法:
- 这是一个字符指针,指向一个字符串字面量(常量字符串)。
s2
可以重新指向其他字符串,但不能修改它指向的字符串内容。
底层实现:
s2
指向了只读的字符串字面量区域,该区域的内容不能修改。- 尝试通过
s2
修改字符串内容会导致未定义行为,因为字符串字面量是不可变的。
示例:
s2 = "world"; // 合法,可以让指针指向另一个字符串字面量
// s2[0] = 'H'; // 不合法,会导致未定义行为,因为尝试修改只读内存
总结
- 字符串字面量 (
"hello"
):不可修改的字符数组,存储在只读内存区。 - 字符数组 (
char s[] = "hello"
):可修改的字符数组,存储在栈或全局/静态区,含有\0
结束标记。 - 字符指针 (
char *s2 = "hello"
):指向字符串字面量的指针,可以重新赋值,但不能修改指向内容。