数据类型

数据:程序的核心

数据类型是C语言的基础,它决定了数据的存储方式和操作方式。东巴文(db-w.cn) 将带你深入理解C语言的数据类型,掌握数据的本质。

💡 东巴文观点:数据类型就像不同规格的容器,选择合适的容器才能高效存储和处理数据。

数据类型分类

C语言数据类型体系

东巴文数据类型分类图

C语言数据类型
├── 基本类型
│   ├── 整数类型
│   │   ├── char(字符型)
│   │   ├── short(短整型)
│   │   ├── int(整型)
│   │   ├── long(长整型)
│   │   └── long long(长长整型)
│   ├── 浮点类型
│   │   ├── float(单精度)
│   │   ├── double(双精度)
│   │   └── long double(长双精度)
│   └── 枚举类型
│       └── enum
├── 构造类型
│   ├── 数组类型
│   ├── 结构体类型
│   │   └── struct
│   ├── 共用体类型
│   │   └── union
│   └── 枚举类型
│       └── enum
├── 指针类型
│   └── type *
└── 空类型
    └── void

整数类型

整数类型详解

东巴文整数类型表

类型 字节数 取值范围 东巴文示例 东巴文应用场景
char 1 -128 ~ 127 char c = 'A'; 字符、小范围整数
unsigned char 1 0 ~ 255 unsigned char uc = 255; 字节、颜色值
short 2 -32768 ~ 32767 short s = 1000; 节省内存的小整数
unsigned short 2 0 ~ 65535 unsigned short us = 50000; 端口号、文件属性
int 4 -2147483648 ~ 2147483647 int i = 100000; 一般整数运算
unsigned int 4 0 ~ 4294967295 unsigned int ui = 4000000000; 大计数、位运算
long 4/8 平台相关 long l = 100000L; 大整数
unsigned long 4/8 平台相关 unsigned long ul = 100000UL; 文件大小、地址
long long 8 ±9.2×10¹⁸ long long ll = 1000000000000LL; 超大整数
unsigned long long 8 0 ~ 1.8×10¹⁹ unsigned long long ull = 1000000000000ULL; 极大计数

查看类型大小

#include <stdio.h>
#include <limits.h>

int main() {
    printf("=== 东巴文数据类型大小查询 ===\n\n");
    
    printf("整数类型:\n");
    printf("char: %zu 字节, 范围: %d ~ %d\n", 
           sizeof(char), CHAR_MIN, CHAR_MAX);
    printf("short: %zu 字节, 范围: %d ~ %d\n", 
           sizeof(short), SHRT_MIN, SHRT_MAX);
    printf("int: %zu 字节, 范围: %d ~ %d\n", 
           sizeof(int), INT_MIN, INT_MAX);
    printf("long: %zu 字节, 范围: %ld ~ %ld\n", 
           sizeof(long), LONG_MIN, LONG_MAX);
    printf("long long: %zu 字节, 范围: %lld ~ %lld\n", 
           sizeof(long long), LLONG_MIN, LLONG_MAX);
    
    return 0;
}

东巴文提示:字节数可能因平台而异,使用 sizeof 查看实际大小。

整数字面量

东巴文整数字面量表示法

#include <stdio.h>

int main() {
    // 十进制
    int dec = 255;
    
    // 八进制(以0开头)
    int oct = 0377;  // 等于255
    
    // 十六进制(以0x或0X开头)
    int hex1 = 0xFF;   // 等于255
    int hex2 = 0xff;   // 等于255
    
    // 二进制(C23标准,以0b或0B开头)
    int bin = 0b11111111;  // 等于255
    
    // 后缀
    long l = 255L;
    unsigned int ui = 255U;
    unsigned long ul = 255UL;
    long long ll = 255LL;
    
    printf("十进制:%d\n", dec);
    printf("八进制:%d\n", oct);
    printf("十六进制:%d\n", hex1);
    
    return 0;
}

整数溢出

#include <stdio.h>
#include <limits.h>

int main() {
    int max = INT_MAX;
    
    printf("最大值:%d\n", max);
    printf("最大值 + 1:%d\n", max + 1);  // 溢出,变成最小值
    
    unsigned int umax = UINT_MAX;
    printf("无符号最大值:%u\n", umax);
    printf("无符号最大值 + 1:%u\n", umax + 1);  // 溢出,变成0
    
    return 0;
}

东巴文警告:整数溢出是未定义行为,要特别注意!

浮点类型

浮点类型详解

东巴文浮点类型表

类型 字节数 有效数字 取值范围 东巴文示例 东巴文应用
float 4 6-7位 ±3.4E38 float f = 3.14f; 一般浮点运算
double 8 15-16位 ±1.7E308 double d = 3.14159; 精确计算
long double 12/16 18-19位 更大 long double ld = 3.14159L; 高精度计算

浮点字面量

#include <stdio.h>

int main() {
    // 小数形式
    double d1 = 3.14;
    double d2 = .5;     // 等于0.5
    double d3 = 5.;     // 等于5.0
    
    // 指数形式
    double d4 = 3.14e2;   // 等于314.0
    double d5 = 3.14E-2;  // 等于0.0314
    
    // 后缀
    float f = 3.14f;
    double d = 3.14;
    long double ld = 3.14L;
    
    printf("d1 = %f\n", d1);
    printf("d4 = %f\n", d4);
    printf("d5 = %f\n", d5);
    
    return 0;
}

浮点数精度问题

#include <stdio.h>

int main() {
    float a = 0.1f;
    float b = 0.2f;
    float c = a + b;
    
    printf("a = %.20f\n", a);
    printf("b = %.20f\n", b);
    printf("a + b = %.20f\n", c);
    printf("0.3 = %.20f\n", 0.3f);
    
    // 浮点数比较
    if (c == 0.3f) {
        printf("相等\n");
    } else {
        printf("不相等\n");  // 可能输出这个
    }
    
    return 0;
}

东巴文提示:浮点数有精度问题,不能直接用 == 比较!

浮点数比较的正确方法

#include <stdio.h>
#include <math.h>

int main() {
    double a = 0.1 + 0.2;
    double b = 0.3;
    
    // ❌ 错误的比较方式
    if (a == b) {
        printf("相等\n");
    }
    
    // ✅ 正确的比较方式
    double epsilon = 1e-9;  // 精度阈值
    if (fabs(a - b) < epsilon) {
        printf("相等(误差范围内)\n");
    }
    
    return 0;
}

字符类型

char类型

东巴文字符类型说明

  • char 本质上是整数类型
  • 占用1字节(8位)
  • 用于存储字符的ASCII码

ASCII码表

东巴文ASCII码速查表

字符 ASCII码 字符 ASCII码 字符 ASCII码
'0' 48 'A' 65 'a' 97
'1' 49 'B' 66 'b' 98
'2' 50 'C' 67 'c' 99
... ... ... ... ... ...
'9' 57 'Z' 90 'z' 122

东巴文技巧

  • 大写字母 + 32 = 小写字母
  • 数字字符 - '0' = 数字值

字符示例

#include <stdio.h>

int main() {
    char c1 = 'A';
    char c2 = 65;      // 与'A'相同
    
    printf("字符:%c, ASCII码:%d\n", c1, c1);
    printf("字符:%c, ASCII码:%d\n", c2, c2);
    
    // 字符运算
    char lower = 'a';
    char upper = lower - 32;  // 转大写
    printf("小写:%c, 大写:%c\n", lower, upper);
    
    // 判断字符类型
    char ch = '5';
    if (ch >= '0' && ch <= '9') {
        printf("%c 是数字\n", ch);
    }
    
    if (ch >= 'A' && ch <= 'Z') {
        printf("%c 是大写字母\n", ch);
    }
    
    if (ch >= 'a' && ch <= 'z') {
        printf("%c 是小写字母\n", ch);
    }
    
    return 0;
}

转义字符

东巴文转义字符表

转义字符 含义 ASCII码 东巴文说明
\n 换行 10 移到下一行开头
\r 回车 13 移到当前行开头
\t 水平制表 9 跳到下一个制表位
\v 垂直制表 11 垂直跳格
\b 退格 8 删除前一个字符
\f 换页 12 换页
\a 响铃 7 系统响铃
\\ 反斜杠 92 输出反斜杠
\' 单引号 39 输出单引号
\" 双引号 34 输出双引号
\? 问号 63 输出问号
\0 空字符 0 字符串结束标志
\ooo 八进制 - 八进制表示字符
\xhh 十六进制 - 十六进制表示字符

布尔类型

C89标准

// 使用整数表示布尔值
int is_true = 1;   // 真
int is_false = 0;  // 假

C99标准

#include <stdio.h>
#include <stdbool.h>

int main() {
    bool is_passed = true;
    bool is_failed = false;
    
    printf("通过:%d\n", is_passed);   // 1
    printf("失败:%d\n", is_failed);   // 0
    
    if (is_passed) {
        printf("恭喜通过!\n");
    }
    
    return 0;
}

东巴文说明:C语言中,0表示假,非0表示真。

空类型(void)

void的用途

东巴文void用途表

用途 示例 东巴文说明
函数无返回值 void func(void) 函数不返回任何值
函数无参数 int func(void) 函数不接受任何参数
通用指针 void *ptr 可以指向任何类型
函数返回通用指针 void *malloc(size_t size) 返回通用指针

示例代码

#include <stdio.h>

// 无返回值的函数
void printMessage(void) {
    printf("东巴文教程 - db-w.cn\n");
}

// 无参数的函数
int getNumber(void) {
    return 42;
}

int main() {
    // 调用无返回值函数
    printMessage();
    
    // 调用无参数函数
    int num = getNumber();
    printf("数字:%d\n", num);
    
    // void指针
    int x = 10;
    void *ptr = &x;
    int *intPtr = (int *)ptr;
    printf("值:%d\n", *intPtr);
    
    return 0;
}

类型限定符

const

const int MAX = 100;     // 常量,不能修改
const char *str = "东巴文";  // 指向常量的指针

东巴文说明const 变量必须在定义时初始化,之后不能修改。

volatile

volatile int flag;  // 易变变量,每次都从内存读取

东巴文应用:用于硬件寄存器、多线程共享变量等。

restrict

void func(int * restrict a, int * restrict b) {
    // a和b不会指向同一内存区域
}

东巴文说明restrict 是C99新增的限定符,用于优化。

存储类型

auto

void function() {
    auto int x = 10;  // 默认,通常省略auto
}

东巴文说明:局部变量默认是 auto 类型,自动创建和销毁。

static

#include <stdio.h>

void counter() {
    static int count = 0;  // 静态局部变量
    count++;
    printf("调用次数:%d\n", count);
}

int main() {
    counter();  // 输出:1
    counter();  // 输出:2
    counter();  // 输出:3
    return 0;
}

东巴文说明static 变量只初始化一次,生命周期贯穿整个程序。

extern

// file1.c
int global_var = 100;

// file2.c
extern int global_var;  // 声明外部变量

void function() {
    printf("%d\n", global_var);
}

register

void function() {
    register int i;  // 建议存储在寄存器中
    for (i = 0; i < 1000000; i++) {
        // 频繁使用的变量
    }
}

东巴文提示register 只是建议,编译器可能忽略。

类型转换

隐式类型转换

东巴文隐式转换规则

#include <stdio.h>

int main() {
    int i = 10;
    float f = i;        // int → float
    double d = f;       // float → double
    
    printf("int: %d\n", i);
    printf("float: %f\n", f);
    printf("double: %lf\n", d);
    
    return 0;
}

东巴文转换等级

long double > double > float > unsigned long long > long long > 
unsigned long > long > unsigned int > int

显式类型转换

#include <stdio.h>

int main() {
    int a = 5, b = 2;
    
    // 整数除法
    int result1 = a / b;
    printf("整数除法:%d\n", result1);  // 2
    
    // 浮点除法(强制转换)
    float result2 = (float)a / b;
    printf("浮点除法:%f\n", result2);  // 2.500000
    
    // 另一种方式
    float result3 = a / (float)b;
    printf("浮点除法:%f\n", result3);  // 2.500000
    
    return 0;
}

类型转换风险

#include <stdio.h>

int main() {
    // 大类型转小类型:可能丢失精度
    double d = 3.14159;
    int i = (int)d;
    printf("double %f → int %d\n", d, i);  // 3
    
    // 溢出
    long big = 3000000000L;
    int small = (int)big;
    printf("long %ld → int %d\n", big, small);  // 可能溢出
    
    return 0;
}

东巴文警告:类型转换可能导致数据丢失或溢出,要谨慎使用!

sizeof运算符

基本用法

sizeof(类型)    // 类型大小
sizeof 变量     // 变量大小
sizeof 变量     // 变量大小(可省略括号)

示例代码

#include <stdio.h>

int main() {
    printf("=== 东巴文数据类型大小查询 ===\n\n");
    
    // 基本类型
    printf("基本类型:\n");
    printf("char: %zu 字节\n", sizeof(char));
    printf("short: %zu 字节\n", sizeof(short));
    printf("int: %zu 字节\n", sizeof(int));
    printf("long: %zu 字节\n", sizeof(long));
    printf("long long: %zu 字节\n", sizeof(long long));
    printf("float: %zu 字节\n", sizeof(float));
    printf("double: %zu 字节\n", sizeof(double));
    printf("long double: %zu 字节\n", sizeof(long double));
    
    // 变量
    int x = 10;
    double y = 3.14;
    printf("\n变量:\n");
    printf("x: %zu 字节\n", sizeof x);
    printf("y: %zu 字节\n", sizeof y);
    
    // 数组
    int arr[10];
    printf("\n数组:\n");
    printf("arr: %zu 字节\n", sizeof(arr));
    printf("arr 元素个数:%zu\n", sizeof(arr) / sizeof(arr[0]));
    
    return 0;
}

东巴文提示sizeof 返回 size_t 类型,使用 %zu 格式输出。

typedef

基本用法

typedef int INTEGER;
typedef float REAL;
typedef char* STRING;

INTEGER x = 10;
REAL y = 3.14f;
STRING name = "东巴文";

结构体别名

typedef struct {
    char name[50];
    int age;
    float score;
} Student;

Student stu1 = {"张三", 20, 85.5};

函数指针别名

typedef int (*CompareFunc)(int, int);

int max(int a, int b) {
    return a > b ? a : b;
}

CompareFunc func = max;

东巴文建议:使用 typedef 可以简化复杂的类型声明,提高代码可读性。

东巴文最佳实践

1. 选择合适的类型

// ✅ 根据数据范围选择类型
unsigned char age = 25;           // 年龄:0-255
unsigned short port = 8080;       // 端口号:0-65535
int studentCount = 50000;         // 学生数量
long long fileSize = 1000000000;  // 文件大小

// ❌ 类型选择不当
int age = 25;                     // 浪费内存
short port = 8080;                // 可能溢出

2. 注意整数溢出

#include <stdio.h>
#include <limits.h>

int main() {
    int a = INT_MAX;
    
    // ❌ 可能溢出
    int b = a + 1;
    
    // ✅ 检查溢出
    if (a > INT_MAX - 1) {
        printf("会溢出!\n");
    } else {
        int b = a + 1;
    }
    
    return 0;
}

3. 避免浮点数直接比较

#include <stdio.h>
#include <math.h>

int main() {
    double a = 0.1 + 0.2;
    double b = 0.3;
    
    // ❌ 错误
    if (a == b) { }
    
    // ✅ 正确
    if (fabs(a - b) < 1e-9) { }
    
    return 0;
}

4. 使用有意义的类型名

// ✅ 使用typedef提高可读性
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;

BYTE age = 25;
WORD port = 8080;
DWORD address = 0x7fff0000;

东巴文验证清单

完成本章学习后,请确认:

  • 理解C语言数据类型的分类
  • 掌握整数类型及其取值范围
  • 掌握浮点类型及其精度
  • 理解字符类型和ASCII码
  • 掌握布尔类型的使用
  • 了解void类型的用途
  • 掌握类型限定符的使用
  • 理解存储类型的区别
  • 掌握类型转换的方法
  • 会使用sizeof和typedef

下一步学习

掌握数据类型后,你可以继续学习:

如果遇到问题,欢迎访问 东巴文(db-w.cn) 获取帮助!


东巴文(db-w.cn) - 让编程学习更简单

📦 东巴文数据类型提示:数据类型是编程的基础,选择合适的数据类型是编写高效程序的关键。在 db-w.cn,我们会通过大量实例帮你掌握数据类型的选择和使用!