【C++基础与提高】第二章:C++数据类型系统——构建程序的基础砖石

【C++基础与提高】第二章:C++数据类型系统------构建程序的基础砖石

(持续更新中,欢迎关注!)

文章目录

  • 【C++基础与提高】第二章:C++数据类型系统------构建程序的基础砖石
      • [2.1 数据类型概述------为什么需要不同类型?](#2.1 数据类型概述——为什么需要不同类型?)
      • [2.2 基本数据类型------C++的原子构件](#2.2 基本数据类型——C++的原子构件)
        • [2.2.1 整数类型详解](#2.2.1 整数类型详解)
        • [2.2.2 浮点类型------处理小数的利器](#2.2.2 浮点类型——处理小数的利器)
        • [2.2.3 字符类型------文字世界的通行证](#2.2.3 字符类型——文字世界的通行证)
        • [2.2.4 布尔类型------逻辑判断的核心](#2.2.4 布尔类型——逻辑判断的核心)
      • [2.3 复合数据类型------构建复杂数据结构](#2.3 复合数据类型——构建复杂数据结构)
        • [2.3.1 数组------有序数据集合](#2.3.1 数组——有序数据集合)
        • [2.3.2 结构体------自定义数据类型](#2.3.2 结构体——自定义数据类型)
      • [2.4 类型修饰符------精细化控制内存使用](#2.4 类型修饰符——精细化控制内存使用)
      • [2.5 类型推导------让编译器帮你思考](#2.5 类型推导——让编译器帮你思考)
      • [2.6 类型转换------不同类型间的桥梁](#2.6 类型转换——不同类型间的桥梁)
        • [2.6.1 隐式类型转换](#2.6.1 隐式类型转换)
        • [2.6.2 显式类型转换](#2.6.2 显式类型转换)
      • [2.7 内存占用与对齐------深入了解底层机制](#2.7 内存占用与对齐——深入了解底层机制)
      • [2.8 最佳实践建议](#2.8 最佳实践建议)
      • [2.9 本章小结](#2.9 本章小结)

2.1 数据类型概述------为什么需要不同类型?

在现实世界中,我们需要不同的容器来存储不同类型的物品:用水杯装水,用书包装书,用钱包装钱。同样,在编程世界里,我们也需要不同类型的数据类型来存储和处理各种信息。

C++的数据类型就像程序员的工具箱,每种工具都有其特定用途:

  • 整数类型用于计数和索引
  • 浮点类型用于科学计算
  • 字符类型用于文本处理
  • 布尔类型用于逻辑判断

2.2 基本数据类型------C++的原子构件

2.2.1 整数类型详解

整数类型是C++中最常用的类型之一,用于存储没有小数部分的数值。

cpp 复制代码
#include <iostream>
#include <climits>  // 包含整数类型范围常量

int main() {
    // 不同大小的整数类型
    short s = 32767;           // 通常16位,范围:-32768到32767
    int i = 2147483647;        // 通常32位,范围:-2,147,483,648到2,147,483,647
    long l = 2147483647L;      // 至少32位
    long long ll = 9223372036854775807LL; // 至少64位
    
    std::cout << "short最大值: " << SHRT_MAX << std::endl;
    std::cout << "int最大值: " << INT_MAX << std::endl;
    std::cout << "long最大值: " << LONG_MAX << std::endl;
    std::cout << "long long最大值: " << LLONG_MAX << std::endl;
    
    return 0;
}

有符号 vs 无符号整数:

cpp 复制代码
// 有符号整数(可正可负)
int signed_num = -100;
// 无符号整数(只能为正,包括0)
unsigned int unsigned_num = 100U;

std::cout << "有符号数: " << signed_num << std::endl;     // 输出: -100
std::cout << "无符号数: " << unsigned_num << std::endl;   // 输出: 100
2.2.2 浮点类型------处理小数的利器

浮点类型用于表示带有小数部分的实数:

cpp 复制代码
#include <iostream>
#include <iomanip>  // 用于控制输出格式

int main() {
    float f = 3.14159f;        // 单精度浮点数,约7位有效数字
    double d = 3.141592653589793; // 双精度浮点数,约15位有效数字
    long double ld = 3.141592653589793238L; // 扩展精度浮点数
    
    std::cout << std::fixed << std::setprecision(10);
    std::cout << "float: " << f << std::endl;
    std::cout << "double: " << d << std::endl;
    std::cout << "long double: " << ld << std::endl;
    
    return 0;
}
2.2.3 字符类型------文字世界的通行证

字符类型用于存储单个字符:

cpp 复制代码
#include <iostream>

int main() {
    char c1 = 'A';              // 普通字符
    char c2 = 65;               // ASCII码值
    char c3 = '\n';             // 转义字符(换行)
    wchar_t wc = L'中';          // 宽字符,支持Unicode
    
    std::cout << "字符1: " << c1 << std::endl;  // 输出: A
    std::cout << "字符2: " << c2 << std::endl;  // 输出: A
    std::cout << "换行前";
    std::cout << c3;                           // 换行
    std::cout << "换行后" << std::endl;
    
    return 0;
}

常见转义字符:

  • \n - 换行
  • \t - 制表符
  • \\\](file://f:\\华为攻城狮带你10天搞定C++\\c++基础与提高.pdf) - 反斜杠

  • \" - 双引号
2.2.4 布尔类型------逻辑判断的核心

布尔类型只有两个值:true(真)和false(假):

cpp 复制代码
#include <iostream>

int main() {
    bool is_raining = true;
    bool is_sunny = false;
    
    std::cout << std::boolalpha;  // 以文字形式输出布尔值
    std::cout << "今天下雨吗? " << is_raining << std::endl;  // 输出: true
    std::cout << "今天晴天吗? " << is_sunny << std::endl;    // 输出: false
    
    // 布尔表达式
    int a = 10, b = 20;
    std::cout << "a > b ? " << (a > b) << std::endl;         // 输出: false
    std::cout << "a < b ? " << (a < b) << std::endl;         // 输出: true
    
    return 0;
}

2.3 复合数据类型------构建复杂数据结构

2.3.1 数组------有序数据集合

数组是一系列相同类型元素的集合:

cpp 复制代码
#include <iostream>

int main() {
    // 声明和初始化数组
    int numbers[5] = {1, 2, 3, 4, 5};  // 固定大小数组
    char name[] = "C++";               // 字符数组(字符串)
    
    // 访问数组元素(索引从0开始)
    std::cout << "第一个数字: " << numbers[0] << std::endl;  // 输出: 1
    std::cout << "最后一个数字: " << numbers[4] << std::endl; // 输出: 5
    
    // 修改数组元素
    numbers[2] = 100;
    std::cout << "修改后的第三个数字: " << numbers[2] << std::endl; // 输出: 100
    
    // 遍历数组
    for(int i = 0; i < 5; i++) {
        std::cout << "numbers[" << i << "] = " << numbers[i] << std::endl;
    }
    
    return 0;
}
2.3.2 结构体------自定义数据类型

结构体允许我们将不同类型的数据组合在一起:

cpp 复制代码
#include <iostream>
#include <string>

// 定义结构体
struct Student {
    std::string name;
    int age;
    double score;
    bool is_graduate;
};

int main() {
    // 创建结构体变量
    Student stu1 = {"张三", 20, 85.5, false};
    
    // 访问结构体成员
    std::cout << "学生姓名: " << stu1.name << std::endl;
    std::cout << "学生年龄: " << stu1.age << std::endl;
    std::cout << "学生成绩: " << stu1.score << std::endl;
    std::cout << "是否毕业: " << (stu1.is_graduate ? "是" : "否") << std::endl;
    
    // 修改结构体成员
    stu1.age = 21;
    std::cout << "一年后年龄: " << stu1.age << std::endl;
    
    return 0;
}

2.4 类型修饰符------精细化控制内存使用

C++提供了多种类型修饰符来更精确地控制数据存储:

cpp 复制代码
#include <iostream>

int main() {
    // signed - 有符号(默认)
    signed int si = -100;
    
    // unsigned - 无符号
    unsigned int ui = 100U;
    
    // short - 短整型
    short sh = 32767;
    
    // long - 长整型
    long lo = 2147483647L;
    
    // long long - 更长整型
    long long ll = 9223372036854775807LL;
    
    std::cout << "sizeof(short): " << sizeof(sh) << " bytes" << std::endl;
    std::cout << "sizeof(int): " << sizeof(si) << " bytes" << std::endl;
    std::cout << "sizeof(long): " << sizeof(lo) << " bytes" << std::endl;
    std::cout << "sizeof(long long): " << sizeof(ll) << " bytes" << std::endl;
    
    return 0;
}

2.5 类型推导------让编译器帮你思考

现代C++引入了自动类型推导功能,简化代码编写:

cpp 复制代码
#include <iostream>
#include <typeinfo>  // 用于获取类型信息

int main() {
    // auto关键字 - 自动推导类型
    auto x = 42;           // 推导为int
    auto y = 3.14;         // 推导为double
    auto z = "Hello";      // 推导为const char*
    
    std::cout << "x的类型: " << typeid(x).name() << std::endl;
    std::cout << "y的类型: " << typeid(y).name() << std::endl;
    std::cout << "z的类型: " << typeid(z).name() << std::endl;
    
    // decltype关键字 - 获取表达式的类型
    int a = 10;
    decltype(a) b = 20;    // b的类型与a相同,都是int
    
    std::cout << "a + b = " << (a + b) << std::endl;
    
    return 0;
}

2.6 类型转换------不同类型间的桥梁

2.6.1 隐式类型转换
cpp 复制代码
#include <iostream>

int main() {
    int i = 100;
    double d = i;  // int自动转换为double
    
    std::cout << "int to double: " << d << std::endl;  // 输出: 100
    
    // 混合运算中的类型转换
    int a = 10;
    double b = 3.0;
    double result = a / b;  // int先转换为double再运算
    
    std::cout << "10 / 3.0 = " << result << std::endl;  // 输出: 3.33333
    
    return 0;
}
2.6.2 显式类型转换
cpp 复制代码
#include <iostream>

int main() {
    // C风格强制类型转换
    double pi = 3.14159;
    int int_pi = (int)pi;  // 转换为整数,丢失小数部分
    
    // C++风格强制类型转换
    int int_pi2 = static_cast<int>(pi);
    
    std::cout << "原始值: " << pi << std::endl;      // 输出: 3.14159
    std::cout << "转换后: " << int_pi << std::endl;   // 输出: 3
    
    // 注意潜在的问题
    unsigned int large_uint = 4000000000U;
    int negative_int = static_cast<int>(large_uint);
    
    std::cout << "大无符号数: " << large_uint << std::endl;
    std::cout << "转换为有符号: " << negative_int << std::endl;
    
    return 0;
}

2.7 内存占用与对齐------深入了解底层机制

不同类型在内存中的占用情况:

cpp 复制代码
#include <iostream>

struct Example1 {
    char c;      // 1字节
    int i;       // 4字节
    short s;     // 2字节
};

struct Example2 {
    char c;      // 1字节
    short s;     // 2字节
    int i;       // 4字节
};

int main() {
    std::cout << "char大小: " << sizeof(char) << " 字节" << std::endl;
    std::cout << "int大小: " << sizeof(int) << " 字节" << std::endl;
    std::cout << "double大小: " << sizeof(double) << " 字节" << std::endl;
    std::cout << "Example1大小: " << sizeof(Example1) << " 字节" << std::endl;
    std::cout << "Example2大小: " << sizeof(Example2) << " 字节" << std::endl;
    
    return 0;
}

2.8 最佳实践建议

  1. 选择合适的数据类型

    • 根据数据范围选择合适的整数类型
    • 对于财务计算优先使用整数避免浮点误差
    • 字符串处理优先考虑std::string而非字符数组
  2. 注意边界条件

    cpp 复制代码
    // 错误示例:溢出风险
    short small_num = 32767;
    small_num++;  // 溢出!
    
    // 正确做法:选择合适类型
    int larger_num = 32767;
    larger_num++;
  3. 合理使用类型推导

    cpp 复制代码
    // 清晰明确的情况
    auto result = calculate_something();
    
    // 可能引起混淆的情况,建议显式声明
    auto value = get_unknown_type();  // 不推荐
    SpecificType value = get_unknown_type();  // 推荐

2.9 本章小结

本章详细介绍了C++的数据类型系统,涵盖了:

  • 基本数据类型的特点和使用场景
  • 复合数据类型的定义和操作
  • 类型修饰符的作用和应用
  • 类型推导和转换机制
  • 内存布局和对齐原则

掌握这些基础知识对于编写高效、安全的C++程序至关重要。下一章我们将深入探讨变量和常量的使用,包括作用域、生命周期等重要概念。


专栏预告:第三章将详细介绍变量与常量的概念,探讨作用域、存储类别以及命名规范等内容,帮助读者建立良好的编程习惯。

相关推荐
lsx2024063 小时前
HTML5 新元素
开发语言
先知后行。5 小时前
C/C++八股文
java·开发语言
songyuc5 小时前
【S2ANet】Align Deep Features for Oriented Object Detection 译读笔记
人工智能·笔记·目标检测
程序员buddha5 小时前
C语言数组详解
c语言·开发语言·算法
寻找华年的锦瑟5 小时前
Qt-视频播放器
开发语言·qt
又是忙碌的一天6 小时前
Java IO流
java·开发语言
fish_study_csdn6 小时前
Python内存管理机制
开发语言·python·c python
蒙奇D索大7 小时前
【算法】递归算法的深度实践:从布尔运算到二叉树剪枝的DFS之旅
笔记·学习·算法·leetcode·深度优先·剪枝
卡提西亚7 小时前
C++笔记-25-函数模板
c++·笔记·算法