本文建议收藏,当作数据类型小百科使用
引言:
在计算机的世界里,内存是一片浩瀚无垠的荒原,而数据类型(Data Types),便是我们在这片荒原上建立的秩序。
C语言之所以强大,正因为它是直面内存的语言。当我们声明一个变量时,选择的不仅仅是一个名字,更是在向计算机申请一块特定大小、具有特定解读方式的“领地”。类型决定了比特流的命运:同样的32个比特,在 int眼中是整数,在 float眼中却是科学计数法,而在 void*眼中,它只是一串无意义的地址。这种解读方式的差异,正是程序逻辑复杂性与魅力的根源。
然而,权力越大,责任越重。数据类型也是一把双刃剑。它既是安全的护盾——通过边界检查防止越界;也是隐藏的陷阱——符号位的扩展、精度的丢失往往成为最难调试的Bug源头。理解数据类型,本质上是在理解“限制”与“表达”的平衡:在有限的字节内,如何精准地刻画现实世界的无限信息。
这不仅是语法的学习,更是编程思维的基石。让我们一同走进C语言的数据世界,学会与内存对话。

一、基本数据类型(内置类型)

类型 关键字 典型字节数 取值范围示例 说明
字符型​ char 1 -128 ~ 127 或 0 ~ 255 存储字符或小整数
整型​ int 4 -2³¹ ~ 2³¹-1 最常用的整数类型
短整型 ​short 2 -32768 ~ 32767 节省内存的小整数
长整型​ long 4/8 ≥ int范围 大整数
超长整型 ​long long 8 -2⁶³ ~ 2⁶³-1 C99新增,更大整数
单精度浮点​ float 4 ±3.4e±38 约6~7位有效数字
双精度浮点 ​double 8 ±1.7e±308 约15位有效数字
长双精度​ long double 8/16 更大范围 高精度浮点

注:字节数因编译器和系统而异(32/64位)。可用 sizeof()查看实际大小。

二、类型修饰符

可组合使用以扩展基本类型:

修饰符 作用 示例
signed 有符号(默认) signed int a;
unsigned 无符号(仅非负) unsigned int count;
short 短长度 short int x;
long 长长度 long double d;

三、派生数据类型

类型 声明方式 说明
数组​ int arr[10]; 相同类型元素的集合
指针​ int *p; 存储地址的变量
结构体​ struct { … }; 不同类型成员的集合
联合体​ union { … }; 共享内存的不同类型
枚举​ enum { RED, GREEN }; 命名整数常量

四、void 类型

1.函数返回空值:void func();
2.无类型指针:void *ptr;(可指向任意数据类型)
3.函数无参数:int func(void);

五、类型选择建议

场景 推荐类型
计数(非负) unsigned int
循环索引 size_t(无符号)
布尔标志 _Bool/ bool
精确控制位 uint8_t, uint32_t
金额计算 int64_t(避免浮点误差)

六、printf常用格式控制符

  1. 基本类型
控制符 类型 示例 输出
%d/ %i int printf(“%d”, 10); 10
%u unsigned int printf(“%u”, 10); 10
%ld long printf(“%ld”, 100L); 100
%lld long long printf(“%lld”, 100LL); 100
%c char printf(“%c”, ‘A’); A
%s 字符串 printf(“%s”, “Hi”); Hi
%f float/double printf(“%f”, 3.14); 3.140000
%lf double(C99) printf(“%lf”, 3.14); 3.140000
%e/ %E 科学计数法 printf(“%e”, 123.4); 1.234000e+02
%g/ %G 自动选择 %f/%e printf(“%g”, 123.4); 123.4
%p 指针地址 printf(“%p”, &x); 0x7ffd…
%x/ %X 十六进制 printf(“%x”, 255); ff
%o 八进制 printf(“%o”, 8); 10
%% 输出 % printf(“%%”); %

七、scanf常用格式控制符

控制符 类型 示例
%d int * scanf(“%d”, &a);
%f float * scanf(“%f”, &x);
%lf double * scanf(“%lf”, &y);
%c char * scanf(“%c”, &ch);
%s 字符串 scanf(“%s”, str);
%u unsigned * scanf(“%u”, &n);
%x 十六进制 scanf(“%x”, &hex);

⚠️ 注意:scanf中:
%s遇到空格停止读取
数组名本身就是地址,不要加 &
建议使用 fgets替代 %s防溢出

八、修饰符(增强控制)

  1. 宽度控制
    printf(“%5d”, 12); // 输出:" 12"(右对齐)
    printf(“%-5d”, 12); // 输出:"12 "(左对齐)
  2. 精度控制
    printf(“%.2f”, 3.14159); // 输出:“3.14”
    printf(“%8.2f”, 3.14159); // 输出:" 3.14"
  3. 填充与对齐
    printf(“%05d”, 12); // 输出:“00012”
    printf(“%*d”, 5, 12); // 动态宽度(等价于 %5d)

九、printf vs scanf对照表

对比项 printf scanf
主要作用​ 输出数据到标准输出 输入数据从标准输入
函数原型​ int printf(const char *fmt, …); int scanf(const char *fmt, …);
参数本质​ 值(变量的内容) 地址(变量在内存中的位置)
是否使用 &​ ❌ 不需要 ✅ 除数组/指针外都需要
返回值​ 成功打印的字符数​ 成功读取并赋值的变量个数​
处理字符串​ %s输出字符串 %s读取字符串(遇空格结束)
空白字符处理​ 原样输出 跳过空白(空格、换行、Tab)
缓冲区行为​ 通常行缓冲(遇到 \n刷新) 输入前常清空输入缓冲区
安全性​ 较安全 ⚠️ 易溢出(尤其 %s)
常见错误​ 格式符与变量类型不匹配 忘记加 &、缓冲区残留 \n

从混沌的内存荒原中划定疆域,我们终将明白:数据类型并非束缚思维的枷锁,而是抵御混乱的堤坝。每一个 int的选择、每一次 cast的权衡,都是在有限的比特中寻找确定的答案。愿你在未来的代码中,既能精准丈量每一寸内存的边界,也能在严谨的类型系统中,构建出无限可能的逻辑宇宙。

Logo

免费领 150 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐