🔷 第二章 C++语言基础
📄 一句话概括

字符类型不止 char 一个:还有明确符号性的 signed char(−128~127)和 unsigned char(0~255),以及装汉字用的宽字符 wchar_t / char16_t / char32_t。核心认知:char 占 1 字节,它到底是有符号还是无符号,由编译器决定(多数是有符号)。所以字节值超过 127 时,按 char 读出来会变成负数——这不是数据坏了,是"解读方式"的选择问题。一个中文汉字在 UTF-8 下占 3 字节,单个 char 装不下。

一、char 家族的四个成员

类型 字节 范围 用途
char 1 不确定(看编译器,多半是 −128~127) 装普通 ASCII 字符
signed char 1 −128 ~ 127 需要"明确有符号"时
unsigned char 1 0 ~ 255 装原始字节值(如图片、加密数据的字节)
wchar_t Windows 2 / Linux 4 Unicode 码点 宽字符,装汉字等
char16_t / char32_t 2 / 4 UTF-16 / UTF-32 C++11 引入,跨平台更规范

三个词的区别:

二、为什么"中文会变成负数"

这是初学者最容易困惑的现象,原因很清楚:

一个字节能表示 0~255。
如果按【无符号】读 → 200 就是 200
如果按【有符号】读 → 200 超过了 127,被解释为 -56

因为 char 多半是"有符号"的,所以当你把"字节值大于 127 的数据"(中文、图片、加密结果)塞进 char 再打印,就会看到负数或乱码。

怎么办:

情况 用什么
处理文本(英文、数字符号) char 没问题
处理原始字节(二进制数据、编码转换) unsigned char
处理中文/Unicode 文本 string(第 6 章)或宽字符

一句话判断:你在意"它是哪个字符"就用 char;你在意"它是哪个字节值"就用 unsigned char。

三、编码的层次:为什么需要"宽"字符

编码 一个汉字占几字节 说明
ASCII 装不下 只有 0~127,规定的是英文、数字、标点
GBK 2 中文老编码(国内 Windows 常见)
UTF-8 3 现在的主流,兼容 ASCII
UTF-16 / UTF-32 2 / 4 定长,处理起来规整,宽字符用的就是它

所以:char 只有 1 字节,装不下一个汉字(UTF-8 要 3 字节);要"一个格子装一个汉字",就需要 2 或 4 字节的宽字符。

📝 乱码的真相

你写文件时用 UTF-8 编码保存,读的时候用 GBK 去解——同一个字节序列,按两套规则翻译,出来的就是乱码。"乱码不是数据错了,是两边用的字典不一样"。这也是第一章"Dev-C++ 编码设成 UTF-8"那条设置的意义。

四、动手 Demo:三个实验看清"符号性"

新建 chartype.cpp:

#include <iostream>
using namespace std;

int main() {
    cout << "sizeof(char)   = " << sizeof(char)   << endl;    // 1
    cout << "sizeof(wchar_t)= " << sizeof(wchar_t)<< endl;    // Windows 2

    char c = 200;                    // 超过 127 的字节值
    cout << "char 存 200,当整数读 = " << (int)c << endl;      // 可能是 -56

    unsigned char u = 200;
    cout << "unsigned char 存 200  = " << (int)u << endl;     // 200

    cout << "char 的范围:" << (int)(char)128 << " 起就开始" << endl;
    return 0;
}

看到什么算成功: - char c = 200; 当整数读时变成负数(例如 −56) - unsigned char u = 200; 老老实实是 200

这就是"符号性"的实际影响——同一串字节,换个类型声明,读出来的数值就变了。

30 秒实验:把 char c = 200; 改成 char c = 'A';,(int)c 输出 65(正常)。说明 ASCII 范围内的字符(0~127)不会受符号性影响——问题只在"字节值大于 127"时出现。

五、常见误区

  1. "char 就是装字符的,跟数字无关"——它装的就是数字(编码)。所以才会出现"存 200 打印出 −56"这种事
  2. "中文可以用 char 数组存"——语法上可以(char s[] = "中文"; 就是 3 字节一篇),但每个格子里的值可能显示为负数,且你没法"一个格子对一个汉字"。正式处理中文用 string
  3. "wchar_t 是标准 2 字节"——不统一:Windows 上 2 字节(UTF-16),Linux 上通常 4 字节。跨平台要用 char16_t / char32_t
  4. "乱码是程序写错了"——多半是编码不一致(写用 UTF-8、读用 GBK)。先怀疑编码设置,再怀疑代码
自测四问(点开对答案) 1. `char` 是几字节?有符号还是无符号?——**1 字节**;**由编译器决定**,多数实现是**有符号**(−128~127)。 2. 为什么 `char c = 200;` 打印出来是负数?——200 超过有符号 `char` 的上限 127,被解释成负数;**要 0~255 请用 `unsigned char`**。 3. 一个汉字在 UTF-8 下占几字节?——**3 字节**,所以单个 `char` 装不下。 4. 乱码通常是为什么?——**编码不一致**:存/读用了不同的编码规则(UTF-8 与 GBK 互读)。

相关笔记