Skip to content

数据类型

C++提供了丰富的数据类型,包括基本数据类型、复合数据类型和用户自定义类型。本章将详细介绍C++的数据类型。

数据类型分类

cpp
#include <iostream>
using namespace std;

/*
 * C++数据类型分类:
 * 
 * 1. 基本数据类型(内置类型)
 *    - 整型:short, int, long, long long
 *    - 字符型:char, wchar_t, char16_t, char32_t
 *    - 浮点型:float, double, long double
 *    - 布尔型:bool
 *    - 空类型:void
 * 
 * 2. 复合数据类型
 *    - 数组
 *    - 指针
 *    - 引用
 *    - 函数
 * 
 * 3. 用户自定义类型
 *    - 结构体(struct)
 *    - 联合体(union)
 *    - 枚举(enum)
 *    - 类(class)
 */

int main() {
    // 显示各类型的大小
    cout << "===== 基本数据类型大小 =====" << endl;
    cout << "bool: " << sizeof(bool) << " 字节" << endl;
    cout << "char: " << sizeof(char) << " 字节" << endl;
    cout << "short: " << sizeof(short) << " 字节" << endl;
    cout << "int: " << sizeof(int) << " 字节" << endl;
    cout << "long: " << sizeof(long) << " 字节" << endl;
    cout << "long long: " << sizeof(long long) << " 字节" << endl;
    cout << "float: " << sizeof(float) << " 字节" << endl;
    cout << "double: " << sizeof(double) << " 字节" << endl;
    
    return 0;
}

整型

cpp
#include <iostream>
#include <climits>  // 包含整型极限值
using namespace std;

int main() {
    // ============ 基本整型 ============
    
    // short:短整型(至少16位)
    short s = 100;
    
    // int:整型(至少16位,通常32位)
    int i = 100000;
    
    // long:长整型(至少32位)
    long l = 1000000L;  // L后缀表示long
    
    // long long:超长整型(至少64位)
    long long ll = 1000000000000LL;  // LL后缀表示long long
    
    
    // ============ 有符号与无符号 ============
    
    // 有符号整型(可以表示负数)
    signed int si = -100;
    
    // 无符号整型(只能表示非负数)
    unsigned int ui = 100U;  // U后缀表示unsigned
    
    // 无符号长整型
    unsigned long ul = 100UL;  // UL后缀
    
    // 无符号超长整型
    unsigned long long ull = 100ULL;  // ULL后缀
    
    
    // ============ 整型极限值 ============
    
    cout << "===== 整型范围 =====" << endl;
    
    // int的范围
    cout << "int最小值: " << INT_MIN << endl;
    cout << "int最大值: " << INT_MAX << endl;
    
    // unsigned int的范围
    cout << "unsigned int最大值: " << UINT_MAX << endl;
    
    // long long的范围
    cout << "long long最小值: " << LLONG_MIN << endl;
    cout << "long long最大值: " << LLONG_MAX << endl;
    
    // unsigned long long的范围
    cout << "unsigned long long最大值: " << ULLONG_MAX << endl;
    
    
    // ============ 整型溢出 ============
    
    short overflow = 32767;  // short最大值
    overflow = overflow + 1; // 溢出!变成-32768
    
    cout << "\n溢出示例:" << endl;
    cout << "32767 + 1 = " << overflow << endl;  // 输出-32768
    
    // 使用无符号类型避免负数溢出
    unsigned short safe = 65535;
    safe = safe + 1;  // 溢出到0
    cout << "65535 + 1 = " << safe << endl;  // 输出0
    
    
    // ============ 整数字面量 ============
    
    // 十进制
    int decimal = 100;
    
    // 八进制(以0开头)
    int octal = 0100;  // 等于十进制的64
    cout << "\n八进制0100 = " << octal << endl;
    
    // 十六进制(以0x或0X开头)
    int hexa = 0x100;  // 等于十进制的256
    cout << "十六进制0x100 = " << hexa << endl;
    
    // 二进制(C++14,以0b或0B开头)
    int binary = 0b100;  // 等于十进制的4
    cout << "二进制0b100 = " << binary << endl;
    
    // 数字分隔符(C++14,使用单引号)
    int million = 1'000'000;  // 提高可读性
    cout << "一百万 = " << million << endl;
    
    return 0;
}

浮点型

cpp
#include <iostream>
#include <cfloat>  // 包含浮点型极限值
#include <iomanip>
using namespace std;

int main() {
    // ============ 浮点类型 ============
    
    // float:单精度浮点型(通常32位)
    float f = 3.14f;  // f或F后缀表示float
    
    // double:双精度浮点型(通常64位)
    double d = 3.14;  // 默认小数是double类型
    
    // long double:扩展精度浮点型
    long double ld = 3.14L;  // L后缀表示long double
    
    
    // ============ 浮点型精度 ============
    
    cout << "===== 浮点型精度 =====" << endl;
    cout << "float精度位数: " << FLT_DIG << endl;        // 通常6位
    cout << "double精度位数: " << DBL_DIG << endl;       // 通常15位
    cout << "long double精度位数: " << LDBL_DIG << endl; // 通常18位
    
    cout << fixed << setprecision(20);
    
    float pi_f = 3.14159265358979323846f;
    double pi_d = 3.14159265358979323846;
    long double pi_ld = 3.14159265358979323846L;
    
    cout << "\nfloat: " << pi_f << endl;
    cout << "double: " << pi_d << endl;
    cout << "long double: " << pi_ld << endl;
    
    
    // ============ 科学计数法 ============
    
    double avogadro = 6.022e23;     // 阿伏伽德罗常数
    double electron = 1.6e-19;      // 电子电荷
    
    cout << scientific;
    cout << "\n阿伏伽德罗常数: " << avogadro << endl;
    cout << "电子电荷: " << electron << endl;
    
    
    // ============ 特殊浮点值 ============
    
    // 正无穷
    double positiveInf = INFINITY;
    cout << "\n正无穷: " << positiveInf << endl;
    
    // 负无穷
    double negativeInf = -INFINITY;
    cout << "负无穷: " << negativeInf << endl;
    
    // 非数字(NaN)
    double nanValue = NAN;
    cout << "NaN: " << nanValue << endl;
    
    // 检查特殊值
    cout << "\nisinf(INFINITY): " << isinf(positiveInf) << endl;
    cout << "isnan(NAN): " << isnan(nanValue) << endl;
    cout << "isfinite(3.14): " << isfinite(3.14) << endl;
    
    
    // ============ 浮点数比较 ============
    
    double a = 0.1 + 0.2;
    double b = 0.3;
    
    cout << defaultfloat;
    cout << "\n0.1 + 0.2 = " << a << endl;
    cout << "0.3 = " << b << endl;
    
    // 直接比较可能失败(浮点精度问题)
    if (a == b) {
        cout << "a == b" << endl;
    } else {
        cout << "a != b (浮点精度问题)" << endl;
    }
    
    // 正确的比较方法:使用epsilon
    double epsilon = 1e-9;
    if (abs(a - b) < epsilon) {
        cout << "a ≈ b (使用epsilon比较)" << endl;
    }
    
    return 0;
}

字符型

cpp
#include <iostream>
#include <string>
using namespace std;

int main() {
    // ============ char类型 ============
    
    // char:存储单个字符(通常1字节)
    char ch1 = 'A';        // 字符字面量
    char ch2 = 65;         // ASCII码值('A'的ASCII码是65)
    char ch3 = '\x41';     // 十六进制转义序列('A')
    
    cout << "ch1 = " << ch1 << endl;
    cout << "ch2 = " << ch2 << endl;
    cout << "ch3 = " << ch3 << endl;
    
    
    // ============ signed char 和 unsigned char ============
    
    // signed char:-128 到 127
    signed char sc = -10;
    
    // unsigned char:0 到 255
    unsigned char uc = 200;
    
    cout << "\nsigned char: " << (int)sc << endl;
    cout << "unsigned char: " << (int)uc << endl;
    
    
    // ============ 宽字符类型 ============
    
    // wchar_t:宽字符类型(存储Unicode字符)
    wchar_t wc = L'中';  // L前缀表示宽字符
    wcout << L"\n宽字符: " << wc << endl;
    
    // char16_t:UTF-16字符(C++11)
    char16_t c16 = u'中';  // u前缀
    
    // char32_t:UTF-32字符(C++11)
    char32_t c32 = U'中';  // U前缀
    
    // char8_t:UTF-8字符(C++20)
    // char8_t c8 = u8'中';  // u8前缀(C++20)
    
    
    // ============ 转义字符 ============
    
    cout << "\n===== 转义字符 =====" << endl;
    cout << "换行符\\n: " << "Hello\nWorld" << endl;
    cout << "制表符\\t: " << "A\tB" << endl;
    cout << "回车符\\r: " << "ABC\rXY" << endl;  // XY替换ABC的前两个
    cout << "反斜杠\\\\: " << "C:\\Path" << endl;
    cout << "单引号\\': " << "\'" << endl;
    cout << "双引号\\\": " << "\"" << endl;
    cout << "空字符\\0: " << "End\0" << endl;
    
    
    // ============ 字符处理函数 ============
    
    #include <cctype>
    
    char test = 'a';
    
    cout << "\n===== 字符处理函数 =====" << endl;
    cout << "isalpha('a'): " << isalpha(test) << endl;    // 是否字母
    cout << "isdigit('a'): " << isdigit(test) << endl;    // 是否数字
    cout << "islower('a'): " << islower(test) << endl;    // 是否小写
    cout << "isupper('a'): " << isupper(test) << endl;    // 是否大写
    cout << "isspace(' '): " << isspace(' ') << endl;     // 是否空白
    cout << "toupper('a'): " << (char)toupper(test) << endl;  // 转大写
    cout << "tolower('A'): " << (char)tolower('A') << endl;   // 转小写
    
    return 0;
}

布尔型

cpp
#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    // ============ bool类型 ============
    
    // bool:布尔类型,只有true和false两个值
    bool isTrue = true;
    bool isFalse = false;
    
    cout << "isTrue = " << isTrue << endl;    // 输出1
    cout << "isFalse = " << isFalse << endl;  // 输出0
    
    // 使用boolalpha输出true/false
    cout << boolalpha;
    cout << "isTrue = " << isTrue << endl;    // 输出true
    cout << "isFalse = " << isFalse << endl;  // 输出false
    
    
    // ============ 布尔值与整数转换 ============
    
    // 整数转布尔:非零为true,零为false
    bool b1 = 0;     // false
    bool b2 = 1;     // true
    bool b3 = -1;    // true(非零)
    bool b4 = 0.0;   // false
    bool b5 = 0.1;   // true
    
    cout << noboolalpha;
    cout << "\n整数转布尔:" << endl;
    cout << "bool(0) = " << b1 << endl;
    cout << "bool(1) = " << b2 << endl;
    cout << "bool(-1) = " << b3 << endl;
    
    // 布尔转整数:true为1,false为0
    int i1 = true;   // 1
    int i2 = false;  // 0
    cout << "\n布尔转整数:" << endl;
    cout << "int(true) = " << i1 << endl;
    cout << "int(false) = " << i2 << endl;
    
    
    // ============ 布尔运算 ============
    
    bool a = true;
    bool b = false;
    
    cout << "\n布尔运算:" << endl;
    cout << boolalpha;
    cout << "true && false = " << (a && b) << endl;  // 逻辑与
    cout << "true || false = " << (a || b) << endl;  // 逻辑或
    cout << "!true = " << !a << endl;                 // 逻辑非
    
    
    // ============ 在条件中使用 ============
    
    int score = 75;
    bool passed = (score >= 60);  // 条件表达式返回bool
    
    cout << "\n分数: " << score << endl;
    cout << "及格: " << passed << endl;
    
    if (passed) {
        cout << "恭喜,你及格了!" << endl;
    } else {
        cout << "很遗憾,你需要补考。" << endl;
    }
    
    return 0;
}

void类型

cpp
#include <iostream>
using namespace std;

// void作为函数返回类型
void printMessage(string msg) {
    cout << msg << endl;
    // 无返回值
}

// void作为函数参数(表示无参数)
int getValue(void) {
    return 42;
}

// void指针可以指向任何类型
void printAnyType(void* ptr, char type) {
    switch (type) {
        case 'i':  // int
            cout << "int: " << *(int*)ptr << endl;
            break;
        case 'd':  // double
            cout << "double: " << *(double*)ptr << endl;
            break;
        case 'c':  // char
            cout << "char: " << *(char*)ptr << endl;
            break;
    }
}

int main() {
    // ============ void作为返回类型 ============
    
    printMessage("Hello, void!");
    
    
    // ============ void指针 ============
    
    int num = 10;
    double pi = 3.14;
    char ch = 'A';
    
    // void指针可以指向任何类型
    void* ptr;
    
    ptr = &num;
    cout << "\nvoid指针指向int: " << *(int*)ptr << endl;
    
    ptr = &pi;
    cout << "void指针指向double: " << *(double*)ptr << endl;
    
    ptr = &ch;
    cout << "void指针指向char: " << *(char*)ptr << endl;
    
    // 使用通用打印函数
    cout << "\n通用打印函数:" << endl;
    printAnyType(&num, 'i');
    printAnyType(&pi, 'd');
    printAnyType(&ch, 'c');
    
    
    // 注意:不能定义void类型的变量
    // void v;  // 错误!
    
    return 0;
}

类型转换

隐式类型转换

cpp
#include <iostream>
using namespace std;

int main() {
    // ============ 算术转换 ============
    
    // 小类型自动提升为大类型
    short s = 10;
    int i = s;      // short -> int(提升)
    long l = i;     // int -> long(提升)
    
    // 有符号转无符号(可能出问题)
    int negative = -1;
    unsigned int positive = negative;  // 变成很大的正数
    cout << "int(-1) -> unsigned: " << positive << endl;
    
    // 整型转浮点
    int intVal = 10;
    double doubleVal = intVal;  // int -> double
    cout << "int(10) -> double: " << doubleVal << endl;
    
    // 浮点转整型(截断小数部分)
    double pi = 3.14159;
    int intPi = pi;  // 截断为3
    cout << "double(3.14159) -> int: " << intPi << endl;
    
    
    // ============ 混合运算转换 ============
    
    int a = 5;
    double b = 2.0;
    
    // int和double运算,int提升为double
    auto result = a / b;  // result是double类型
    cout << "\n5 / 2.0 = " << result << endl;
    
    // 整数除法
    int intDiv = 5 / 2;  // 结果是2(整数除法)
    cout << "5 / 2 = " << intDiv << endl;
    
    
    // ============ 赋值转换 ============
    
    double d = 3.9;
    int n = d;  // 截断,n = 3
    cout << "\ndouble(3.9) -> int: " << n << endl;
    
    // 警告:精度丢失
    long long bigNum = 9223372036854775807LL;
    int smallNum = bigNum;  // 溢出!
    cout << "long long -> int: " << smallNum << endl;
    
    return 0;
}

显式类型转换

cpp
#include <iostream>
#include <string>
using namespace std;

int main() {
    // ============ C风格转换 ============
    
    double pi = 3.14159;
    
    // C风格:(类型)表达式
    int intPi1 = (int)pi;
    cout << "C风格转换: " << intPi1 << endl;
    
    // 函数风格:类型(表达式)
    int intPi2 = int(pi);
    cout << "函数风格转换: " << intPi2 << endl;
    
    
    // ============ C++风格转换(推荐) ============
    
    // static_cast:静态转换(编译时检查)
    double d = 3.14;
    int i = static_cast<int>(d);
    cout << "\nstatic_cast<double->int>: " << i << endl;
    
    // 相关类型之间的转换
    char c = 'A';
    int ascii = static_cast<int>(c);
    cout << "static_cast<char->int>: " << ascii << endl;
    
    
    // ============ const_cast ============
    
    // 移除const属性(慎用!)
    const int constVal = 10;
    // constVal = 20;  // 错误:不能修改const变量
    
    int* ptr = const_cast<int*>(&constVal);
    *ptr = 20;  // 危险!可能导致未定义行为
    cout << "\nconst_cast后: " << constVal << endl;
    
    // 常用于函数参数传递
    void printString(const string& s) {
        // 如果需要修改s,可以使用const_cast
        // 但通常不应该这样做
    }
    
    
    // ============ reinterpret_cast ============
    
    // 重新解释位模式(危险,慎用)
    int num = 65;
    int* intPtr = &num;
    
    // 将int指针转为char指针
    char* charPtr = reinterpret_cast<char*>(intPtr);
    cout << "\nreinterpret_cast后: " << *charPtr << endl;
    
    // 指针与整数之间的转换
    long long ptrValue = reinterpret_cast<long long>(intPtr);
    cout << "指针转整数: " << ptrValue << endl;
    
    
    // ============ dynamic_cast ============
    
    // 用于多态类型的向下转型(需要虚函数)
    class Base {
    public:
        virtual ~Base() {}
    };
    
    class Derived : public Base {
    public:
        void derivedMethod() {
            cout << "Derived method" << endl;
        }
    };
    
    Base* basePtr = new Derived();
    
    // 安全的向下转型
    Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);
    if (derivedPtr) {
        cout << "\ndynamic_cast成功" << endl;
        derivedPtr->derivedMethod();
    }
    
    delete basePtr;
    
    
    // ============ 转换选择建议 ============
    
    /*
     * 选择转换类型的建议:
     * 
     * 1. static_cast:
     *    - 基本类型之间的转换
     *    - 有继承关系的类指针/引用转换
     *    - void*与其他指针之间的转换
     * 
     * 2. const_cast:
     *    - 移除或添加const属性
     *    - 移除或添加volatile属性
     * 
     * 3. reinterpret_cast:
     *    - 指针与整数之间的转换
     *    - 不相关指针类型之间的转换
     *    - 函数指针之间的转换
     * 
     * 4. dynamic_cast:
     *    - 多态类型的向下转型
     *    - 需要运行时类型检查
     */
    
    return 0;
}

auto关键字

cpp
#include <iostream>
#include <vector>
#include <map>
#include <memory>
using namespace std;

// 函数返回类型推导(C++14)
auto add(int a, int b) {
    return a + b;  // 返回类型推导为int
}

// 返回类型后置(C++11)
auto multiply(int a, int b) -> int {
    return a * b;
}

int main() {
    // ============ 基本用法 ============
    
    // 自动推导变量类型
    auto num = 10;          // int
    auto pi = 3.14;         // double
    auto ch = 'A';          // char
    auto str = "hello";     // const char*
    auto flag = true;       // bool
    
    cout << "auto推导的基本类型" << endl;
    cout << "num类型大小: " << sizeof(num) << endl;
    cout << "pi类型大小: " << sizeof(pi) << endl;
    
    
    // ============ 推导引用和const ============
    
    int x = 10;
    const int cx = 20;
    
    // auto会忽略顶层const和引用
    auto a1 = x;       // int
    auto a2 = cx;      // int(忽略了const)
    auto& a3 = cx;     // const int&(保留const)
    
    // 使用auto&保留const
    const auto& a4 = x;  // const int&
    
    // auto&& 通用引用
    auto&& r1 = x;     // int&(左值引用)
    auto&& r2 = 10;    // int&&(右值引用)
    
    
    // ============ 简化复杂类型 ============
*
    // 传统写法
    map<string, vector<int>> data;
    map<string, vector<int>>::iterator it1 = data.begin();
    
    // 使用auto简化
    auto it2 = data.begin();  // 更简洁
    
    // 智能指针
    auto ptr = make_unique<int>(42);  // unique_ptr<int>
    auto sptr = make_shared<int>(42); // shared_ptr<int>
    
    cout << "\n智能指针值: " << *ptr << endl;
    
    
    // ============ 范围for循环 ============
    
    vector<int> numbers = {1, 2, 3, 4, 5};
    
    cout << "\n范围for循环:" << endl;
    
    // 使用auto
    for (auto n : numbers) {
        cout << n << " ";
    }
    cout << endl;
    
    // 使用auto&修改元素
    for (auto& n : numbers) {
        n *= 2;
    }
    
    // 使用const auto&只读访问
    for (const auto& n : numbers) {
        cout << n << " ";
    }
    cout << endl;
    
    
    // ============ 函数返回类型推导 ============
    
    auto sum = add(10, 20);
    auto product = multiply(5, 6);
    
    cout << "\nadd(10, 20) = " << sum << endl;
    cout << "multiply(5, 6) = " << product << endl;
    
    
    // ============ auto使用建议 ============
    
    /*
     * auto使用建议:
     * 
     * 优点:
     * 1. 简化代码,特别是复杂类型
     * 2. 避免类型拼写错误
     * 3. 保证变量初始化
     * 4. 重构时自动适应类型变化
     * 
     * 注意事项:
     * 1. 可读性:确保类型显而易见
     * 2. 避免意外的类型转换
     * 3. 使用auto&避免不必要的拷贝
     * 4. 使用const auto&表示只读
     */
    
    return 0;
}

本章小结

本章学习了:

  • 整型:short、int、long、long long,有符号与无符号
  • 浮点型:float、double、long double,精度与科学计数法
  • 字符型:char、wchar_t、char16_t、char32_t,转义字符
  • 布尔型:true和false,与整数的转换
  • void类型:函数返回值、void指针
  • 类型转换:隐式转换、static_cast等C++风格转换
  • auto关键字:自动类型推导,简化复杂类型

下一章,我们将学习运算符,了解C++中的各种运算操作。