C++中双引号和单引号的区别(全面分析)
·
我在刷算法题的时候经常遇到,用了' '出现警告或者使用" "直接报错,尤其是在字符串部分(py玩家后遗症/(ㄒoㄒ)/~~)在详细了解后总结一下加强记忆。
总的来说在 C++ 中,双引号 "" 和单引号 '' 是完全不同的语法元素,数据类型、存储方式有所差异。
| 对比维度 | 单引号 ''(字符常量) |
双引号 ""(字符串常量) |
|---|---|---|
| 数据类型 | char |
const char[](字符数组) |
| 存储内容 | 单个字符的 ASCII 码 | 字符序列 + 末尾 '\0' 结束符 |
| 占用字节 | 固定 1 字节 | 字符数 + 1 字节(含 '\0') |
| 内容限制 | 仅 1 个字符(非空) | 0 个或多个字符(可空) |
| 赋值对象 | char 变量 |
const char* / char[] |
| 隐式转换 | 可转 int(ASCII 码) |
可转 const char*(首地址) |
| 示例 | '5'、'\t'、'Z' |
""、"abc"、"x\ny" |
一、核心定义与数据类型
这是最根本的区别:单引号表示字符常量(char 类型),双引号表示字符串常量(const char[] 类型,本质是字符数组)。
| 符号 | 表示内容 | 数据类型 | 本质含义 |
|---|---|---|---|
'a' |
单个字符常量 | char |
单个 ASCII 字符 |
"a" |
字符串常量 | const char[] |
以 '\0' 结尾的字符数组 |
二、存储方式与字节长度
两者在内存中的存储形式和占用字节数完全不同,这是导致后续所有区别的根源。
1. 单引号(字符常量)
- 存储:直接存储单个字符的 ASCII 码值,占用 1 个字节(
char类型的标准大小)。 - 示例:
'A'在内存中存储为 ASCII 码65(二进制01000001),仅占 1 字节。 - 长度计算:
sizeof('A') == 1(固定为 1,与字符无关)。
2. 双引号(字符串常量)
- 存储:本质是 字符数组,除了显式的字符外,末尾会自动添加一个
'\0'空字符(作为字符串结束标志),总占用字节数 = 显式字符数 + 1。 - 示例:
"A"在内存中实际是{'A', '\0'},占用 2 字节;"hello"是{'h','e','l','l','o','\0'},占用 6 字节。 - 长度计算:
sizeof("A") == 2(包含'\0'的总字节数);strlen("A") == 1(strlen统计'\0'之前的字符数,需包含<cstring>头文件)。
三、语法规则:内容限制不同
C++ 对两者的语法有严格限制,违反会导致编译错误。
1. 单引号 '' 的限制
- 只能包含 1 个字符:不能为空(
''编译错误),也不能包含多个字符('ab'是「多字符常量」,语法不推荐,值为各字符 ASCII 码的组合,结果不确定)。 - 合法示例:
'5'、'+'、'\n'(转义字符,本质是单个字符,ASCII 码为 10)。 - 非法示例:
''(空字符常量,错误)、'12'(多字符,不推荐)。
2. 双引号 "" 的限制
- 可包含 0 个或多个字符:空字符串
""合法(仅存储'\0',占 1 字节),多字符也合法(如"123abc")。 - 支持转义字符:如
"a\nb"表示'a'、换行符'\n'、'b'、'\0',共 4 字节。 - 合法示例:
""(空字符串)、"Hello, C++"、"x\ty"(包含制表符)。 - 非法示例:无本质非法内容,但需注意转义字符的正确性(如
"a\b"合法,"a\z"非法,因为\z不是有效转义符)。
下面代码最能体现区别
string s3 =s1+s2;//bwabwa
cout << s3<<endl;
//-------------插入push_back()和insert() push_back为void类型,删除erase()
s1.push_back('c');
string s4 = s1; //bwac
s4.insert(s4.begin(),'i');//ibwac
s1.erase(s1.begin()+3); //bwa s1.erase(s.begin() + 1, s.begin() + 3); 删除范围
//--------------replace() repalce()函数:s.replace(pos,len,ss),将s从pos开始的len个字符替换成ss,
s3.replace(2,2,"aa"); //bwabwa->bwaawa
cout<<s3<<endl;
//s.replace(pos,n1,n2,c),将s从pos开始的n1个字符替换成n2个字符c。
s3.replace(2,2,1,'z'); //bwaawa-> bwzwa
四、如何选择区分
两者的使用场景严格依赖于变量 / 函数参数的类型,混用会导致编译错误。
1. 单引号 '' 的使用场景
- 给
char类型变量赋值:char c1 = 'a'; // 正确:char 变量匹配字符常量 char c2 = 65; // 正确:等价于 'A'(ASCII 码) char c3 = "a"; // 错误:字符串常量(const char[])无法赋值给 char 变量 - 作为
char类型参数传递给函数:putchar('B'); // 正确:putchar 接收 char 类型 cout << 'c'; // 正确:输出 ASCII 码对应的字符(显示 'c')
2. 双引号 "" 的使用场景
- 给字符串相关类型赋值(字符指针、字符数组):
const char* s1 = "hello"; // 正确:字符串常量赋值给字符指针(指向常量区) char s2[] = "world"; // 正确:字符串常量初始化字符数组(会复制到栈区) char s3[6] = "hello"; // 正确:数组大小 = 字符数 + 1(包含 '\0') char s4[5] = "hello"; // 错误:数组大小不足(需 6 字节,实际仅存 5 个字符,无 '\0') - 作为字符串参数传递给函数:
cpp
puts("Hi!"); // 正确:puts 接收字符串常量 strlen("test"); // 正确:计算字符串长度(结果为 4) cout << "C++"; // 正确:输出字符串(自动识别 '\0' 结束)
五、隐式转换与兼容性
1. 字符常量('c')的隐式转换
- 可隐式转换为
int类型(值为对应的 ASCII 码):int num = '0'; // 正确:num = 48('0' 的 ASCII 码) cout << 'z'; // 输出 122('z' 的 ASCII 码)
2. 字符串常量("c")的隐式转换
- 可隐式转换为
const char*类型(指向字符串的首地址),但不能转换为int或char:const char* p = "abc"; // 正确:p 指向 'a' 的地址 int len = "abc"; // 错误:字符串无法直接转换为 int - 字符串常量是只读的:赋值给非
const指针会导致未定义行为(C++11 后编译器会警告):char* p = "hello"; // 不推荐:"hello" 是 const,修改 p[0] 会崩溃 const char* p = "hello";// 正确:明确只读,避免误修改
六、特殊情况:空值与转义字符
1. 空值处理
- 字符常量无 “空值”:
''非法,若需表示空字符,需用转义字符'\0'(ASCII 码 0):char null_char = '\0'; // 正确:表示空字符(占 1 字节) - 字符串常量可有空值:
""是合法的空字符串,仅包含'\0'(占 1 字节):const char* empty_str = ""; cout << strlen(empty_str); // 输出 0(无有效字符) cout << sizeof(empty_str); // 输出 8(指针大小,64 位系统) cout << sizeof(""); // 输出 1(仅 '\0')
2. 转义字符的使用
- 单引号中:转义字符需用
\,如'\''表示字符','\n'表示换行符。 - 双引号中:转义字符同样需用
\,如"\""表示字符串","a\\b"表示字符串a\b。
常见错误示例与原因
- 错误 1:字符串赋值给
char变量char c = "a"; // 错误:类型不匹配(const char[] → char) - 错误 2:单引号包含多个字符
char c = 'ab'; // 不推荐:多字符常量,值为 0x6162(依赖编译器,结果不确定) - 错误 3:字符串数组未留
'\0'空间char arr[3] = "abc"; // 错误:"abc" 需 4 字节(含 '\0'),数组仅 3 字节,截断导致无结束符 - 错误 4:修改字符串常量
char* s = "hello"; s[0] = 'H'; // 未定义行为:"hello" 是只读常量,修改会崩溃
更多推荐



所有评论(0)