提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
关于字符数组我很多都不会了
char arr[]="哈哈";
这行代码我就有两个问题
1、字符数组可以用字符串赋值是吗,记得以前都是用的{'','',''}着这种
2、char里面还可以存汉字吗,char不是ascii相关得吗,值只能是0-127吧
char a = 'a';
char b = 97;
char c = '哈';
cout << a << endl;
cout << b << endl;
cout << c << endl;
像a b这种赋值我能理解,c这种直接给汉字包括你的char arr[]="哈哈";这种代码为什么可以
以及char d=666;这种超过ascii码赋值又会怎么样
你现在核心想弄清楚char arr[]="哈哈"中字符串赋值的合法性、char类型能存储汉字的原因,以及char变量赋值超过ASCII范围(比如666)的行为——这些都是C/C++中char类型和字符编码的核心基础问题,我会用最通俗的语言拆解,让你彻底理解。
问题1:字符数组可以用字符串赋值吗?和{}赋值的区别
结论先明确:完全可以!char arr[] = "哈哈"; 是C/C++标准明确支持的合法语法,和{}初始化是两种等价但有细节差异的方式,本质都是给数组逐个字节赋值。
1.1 字符串赋值的底层逻辑
当你写char arr[] = "哈哈";时,编译器会自动完成3件事:
- 解析字符串字节:先把"哈哈"按编译器的
execution-charset(比如UTF-8)转换成对应的字节序列(“哈”的UTF-8是0xE5 0x93 0x88,两个“哈”就是0xE5 0x93 0x88 0xE5 0x93 0x88); - 自动补结束符:在字节序列末尾加
\0(ASCII 0,C风格字符串的结束标记); - 推导数组长度+赋值:数组长度自动推导为“字节数+1”(比如UTF-8下是4+1=5),然后把所有字节(包括
\0)逐个拷贝到数组的内存空间中。
1.2 和{}初始化的对比(核心差异)
| 特性 | 字符串赋值 char arr[] = "哈哈" | {} 初始化 char arr[] = {'哈','哈','\0'} |
|---|---|---|
结束符\0 | 自动添加,无需手动写 | 必须手动加,漏写则数组不是“C风格字符串” |
| 长度推导 | 自动推导(字节数+1) | 自动推导(括号内元素个数) |
| 可读性 | 高(直接写汉字) | 低(需拆成字节才准确) |
| 合法性 | 仅能用于初始化(不能赋值) | 仅能用于初始化(不能赋值) |
1.3 新手易踩坑的例子
// 1. 字符串赋值(推荐):自动补\0,长度5(UTF-8)
char arr1[] = "哈哈";
// 等价于手动拆字节的{}写法(UTF-8):
char arr2[] = {0xE5, 0x93, 0x88, 0xE5, 0x93, 0x88, 0x00};
// 2. 坑:{}漏写\0,数组不是C风格字符串
char arr3[] = {'哈','哈'}; // 长度2,无\0 → 用strlen(arr3)会越界乱算
// 3. 坑:数组初始化后不能赋值(数组名是常量)
char arr4[10];
arr4 = "哈哈"; // 非法!编译报错(数组名不能被赋值)
问题2:char能存汉字吗?赋值超过ASCII范围会怎样?
这是新手最容易误解的点——char的本质是“1字节整数”,不是“只能存ASCII的字符类型”,ASCII只是char的一种使用场景,不是限制。
2.1 先纠正核心认知:char的本质
C/C++中char是:
- 占用1个字节(8位) 的整数类型(不是“字符专用类型”);
- 分两种(编译器默认是
signed char):signed char:范围-128 ~ 127(对应ASCII的0-127,但负数是扩展编码);unsigned char:范围0 ~ 255(覆盖所有1字节编码);
- 所谓“存字符”,只是把字符的编码值(整数) 存在这1字节里——ASCII是0-127的编码,只是char能存的整数范围的一小部分。
2.2 为什么char arr[] = "哈哈"合法,而char c = '哈'会乱码?
核心:单个汉字是多字节编码,需要多个char拼接存储,单个char存不下!
- 汉字的编码规则(比如UTF-8/GBK):
- UTF-8:一个汉字占2~4字节(“哈”=3字节:
0xE5 0x93 0x88); - GBK:一个汉字占2字节(“哈”=2字节:
0xB9 0xFE);
- UTF-8:一个汉字占2~4字节(“哈”=3字节:
char arr[] = "哈哈":合法!数组有多个char,每个char存汉字编码的一个字节,拼接起来就是完整的汉字;char c = '哈':编译器“妥协支持但逻辑非法”——单char只能存1字节,编译器会截断汉字的多字节,只存最后1字节(比如UTF-8的“哈”只存0x88),所以输出c会是乱码。
2.3 你的代码运行结果解释
char a = 'a'; // 'a'的ASCII是97 → 存整数97,输出'a'
char b = 97; // 直接存整数97 → 等价于a,输出'a'
char c = '哈'; // 截断多字节,只存最后1字节(比如0x88)→ 输出乱码(方块/问号)
cout << a << endl; // 输出:a
cout << b << endl; // 输出:a
cout << c << endl; // 输出:�(乱码)
2.4 char d = 666; 赋值超过ASCII范围会怎样?
核心:char是1字节(8位),赋值超过范围会发生整数截断——只保留二进制的最后8位,然后按signed/unsigned解析。
步骤拆解(以默认signed char为例):
- 把666转二进制:
666 = 2×256 + 154→ 二进制是1010011010(共10位); - 截断低8位:取最后8位 →
010011010?不,补前导0到8位:10011010(十进制154); - 按
signed char解析:10011010是补码,最高位是1(表示负数),转原码:- 补码→反码:
10011001→ 反码→原码:11100110(十进制102); - 最终值:
-102;
- 补码→反码:
- 运行结果:
char d = 666; cout << (int)d << endl; // 输出:-102(signed char)/ 154(unsigned char) cout << d << endl; // 输出:乱码(-102/154不是可打印ASCII)
总结
- 字符数组可以用字符串赋值,编译器会自动解析字符串字节、补
\0并推导长度,和{}初始化的核心差异是自动补结束符; - char的本质是1字节整数,不是只能存ASCII——汉字是多字节编码,需多个char拼接存储,单个char存汉字会截断乱码;
- char赋值超过范围会截断低8位,signed char会溢出为负数,unsigned char保留低8位,最终存储的是截断后的整数,输出多为乱码。
302

被折叠的 条评论
为什么被折叠?



