3、基本数据类型:整型(int/short/long)、浮点型(float/double)、字符型(char)、类型大小与范围
说到C语言的基本数据类型,这其实是我们每天打交道最多的东西。我刚开始学C的时候,觉得不就是几个数字类型嘛,有啥好研究的?后来在项目中吃过亏,才明白这里面的门道比想象中深得多。
3.1 整型家族:int、short、long
整型说白了就是用来存整数的。但C语言给了我们好几个选择,为什么呢?
int 是最常用的整型。在大多数现代系统上,它占4个字节。我个人习惯,只要不是特别在意内存,优先用int。
short 占2个字节,范围小一些。我在嵌入式项目中经常用它,因为内存金贵啊。你想想看,一个传感器采集的温度值,范围也就-40到125度,用short绰绰有余。
long 在32位系统上是4字节,64位系统上是8字节。什么时候用?当你要存很大的数,比如文件大小、时间戳这些。
核心要点:
- int:4字节,范围约-21亿到21亿
- short:2字节,范围-32768到32767
- long:4或8字节,取决于系统
#include <stdio.h>
int main() {
int a = 100;
short b = 200;
long c = 300000L; // L后缀表示long类型
printf("int size: %zu bytes\n", sizeof(a));
printf("short size: %zu bytes\n", sizeof(b));
printf("long size: %zu bytes\n", sizeof(c));
return 0;
}
我曾经踩过的坑:有一次做金融计算,用int存金额,结果数据量大了之后溢出了。客户对账发现少了1块钱,排查了半天。从那以后,涉及金额的我一定用long long。
3.2 浮点型:float 和 double
浮点型用来处理小数。这里有个关键区别——精度。
float 占4字节,有效数字约6-7位。精度有限,但省内存。我在做图形处理时常用,因为颜色值0.0到1.0,float足够了。
double 占8字节,有效数字约15-16位。精度高,是默认的浮点类型。做科学计算、工程模拟,我建议直接用double。
小技巧:写浮点数常量时,float加f后缀,double不加。比如 3.14f 是float,3.14 是double。这能避免不必要的类型转换警告。
#include <stdio.h>
int main() {
float pi_f = 3.141592653589793f;
double pi_d = 3.141592653589793;
printf("float: %.15f\n", pi_f); // 精度不足,后面都是垃圾值
printf("double: %.15f\n", pi_d); // 精度足够
return 0;
}
运行结果会让你大吃一惊。float只能精确到小数点后6位左右,后面的数字完全是随机的。嗯,这就是精度的代价。
3.3 字符型:char
char虽然叫字符型,但它本质上就是一个1字节的整数。存的是ASCII码。
比如 'A' 的ASCII码是65,'0' 是48,空格是32。你可以把char当整数用,也可以把整数当char用。
#include <stdio.h>
int main() {
char ch = 'A';
printf("字符: %c, ASCII码: %d\n", ch, ch);
ch = ch + 1; // 字符运算
printf("加1后: %c, ASCII码: %d\n", ch, ch);
return 0;
}
注意:char可以是signed(-128到127)或unsigned(0到255),具体取决于编译器。如果你要存ASCII字符,用char就行。如果要存字节数据,建议明确写 unsigned char。
3.4 类型大小与范围
不同系统上,类型大小可能不一样。这就是C语言的"实现定义"行为。我建议你养成一个好习惯——用 sizeof 运算符来确认。
| 类型 | 32位系统 | 64位系统 | 范围(32位) |
|---|---|---|---|
| char | 1字节 | 1字节 | -128 ~ 127 或 0 ~ 255 |
| short | 2字节 | 2字节 | -32768 ~ 32767 |
| int | 4字节 | 4字节 | -2^31 ~ 2^31-1 |
| long | 4字节 | 8字节 | -2^31 ~ 2^31-1 或更大 |
| float | 4字节 | 4字节 | 约 ±3.4e-38 ~ ±3.4e38 |
| double | 8字节 | 8字节 | 约 ±1.7e-308 ~ ±1.7e308 |
我曾经踩过的坑:把32位系统上写的代码移植到64位系统,long从4字节变成了8字节,导致二进制文件格式解析全乱了。所以跨平台代码,我建议用 int32_t、int64_t 这些固定宽度的类型。
3.5 知识体系总览
下面这张图帮你理清基本数据类型的关系:
3.6 避坑指南
最后分享几个我实战中遇到的坑:
- 整型溢出:int最大值加1会变成负数。这不是bug,是C语言的设计。所以做循环计数时,注意边界条件。
- 浮点比较:不要直接用 == 比较两个浮点数。因为精度问题,0.1 + 0.2 不一定等于 0.3。用差值小于某个极小值来判断。
- char的符号:如果你用char存非ASCII数据,比如字节流,一定要用 unsigned char。否则大于127的值会被解释成负数。
- sizeof的返回值:sizeof返回的是 size_t 类型,在printf里用 %zu 格式化,别用 %d。
我的建议:写代码时,明确写出类型的大小预期。比如知道数据范围在0-1000,就用unsigned short。这不仅是好习惯,也是给后来维护代码的人传递信息。
基本数据类型看似简单,但用好它们需要理解底层的内存布局和系统差异。你想想看,一个int在不同架构上可能不一样,这就是C语言的灵活之处,也是它的陷阱所在。多写、多测、多踩坑,慢慢就熟练了。