问题描述:
跟下面代码和结果回答下列问题。
代码:
// Created by 黑马程序员.
#include "iostream"
using namespace std;
int main()
{
"hello"; // 底层就是字符数组
char s[] = "hello"; // 底层也是字符数组,会额外添加一个\0作为最后一个元素,当做结束标记
char *s2 = "hello";
cout << s[0] << endl;
cout << s[1] << endl;
cout << s[2] << endl;
cout << s[3] << endl;
cout << s[4] << endl;
cout << s[5] << endl;
cout << sizeof(s) << endl;
for (char i: s)
{
cout << i;
}
return 0;
}
结果
结果
D:\CLion_code\cmake-build-debug\CLion_code.exe
h
e
l
l
o
6
hello
Process finished with exit code 0
问题:
上述2种C语言风格字符串,其存储机制是什么呢?方式1(字面常量)和方式2定义的字符串,其本质都是字符数组。将每一个字符,作为1个元素,存入字符数组中在字符数组中,额外在最后添加一个元素引日(空字符),作为结束标记。
问题解答:
在C++(及C语言)中,字符串可以通过不同方式定义和存储。你提到的两种方式,其存储机制如下:
1. 字符数组方式 (char s[] = "hello";
)
char s[] = "hello";
存储机制:
- 字符数组:在这种定义方式中,字符串
"hello"
被存储为一个字符数组s
,并且额外在字符串末尾自动添加了一个空字符\0
作为字符串的结束标记。 - 内存布局:
s
数组在栈(或静态存储区,如果是全局/静态变量)中分配内存。- 数组
s
实际上存储了 6 个字符:'h'
,'e'
,'l'
,'l'
,'o'
,'\0'
。 sizeof(s)
返回数组的总大小,即 6 字节(5 个字符加上一个结束标记\0
)。
示例结果:
h // s[0]
e // s[1]
l // s[2]
l // s[3]
o // s[4]
// s[5] 是 '\0',显示为空白
2. 字符指针方式 (char *s2 = "hello";
)
char *s2 = "hello";
存储机制:
- 指针指向字符串字面量:在这种定义方式中,
s2
是一个指针,指向常量字符串"hello"
的起始地址。 - 字符串字面量:字符串
"hello"
作为一个字面量,存储在程序的只读内存区域(通常是常量区或只读数据段),并且末尾也会自动添加一个空字符\0
作为结束标记。 - 指针可变但内容不可变:
s2
可以重新指向其他字符串字面量或字符数组,但不能通过s2
修改字符串内容,因为它指向的是只读内存。
内存布局:
s2
指向"hello"
所在的内存区域,这个区域的内容与char s[] = "hello";
中的数组类似,但存储在不同的内存区域。
总结:
- 相同点:两种方式在底层都会存储字符数组,且末尾有一个
\0
作为结束标记。 - 不同点:
char s[] = "hello";
生成了一个可修改的字符数组,存储在栈上或静态存储区;char *s2 = "hello";
是一个指向字符串字面量的指针,存储在只读的内存区域,内容不可修改。