short 与 int
short 和 int 是 C 语言最基本的整数类型,用于存储整数值。它们的大小由编译器和平台决定,但标准规定了最小保证范围。理解它们的取值范围、存储大小和选择策略,能帮助你写出既节省内存又不溢出的代码。
int 类型
int 是 C 语言最常用的整数类型,标准保证它至少为 16 位,在大多数现代平台上是 32 位(4 字节)。
int age = 25;
int temperature = -10;
int count = 0;
printf("sizeof(int) = %zu\n", sizeof(int)); /* 通常是 4 */
int 的取值范围可以通过 <limits.h> 查询:
#include <limits.h>
printf("INT_MIN = %d\n", INT_MIN); /* -2147483648(32 位) */
printf("INT_MAX = %d\n", INT_MAX); /* 2147483647(32 位) */
32 位 int 能表示约 ±21 亿的整数,足以应对大多数日常计算。但如果处理更大的数值(如人口统计、天文计算),需要使用 long long。
short 类型
short(或 short int)是较小的整数类型,标准保证至少 16 位(2 字节),通常就是 16 位。
short small = 100;
short int same = 100; /* 等价 */
printf("sizeof(short) = %zu\n", sizeof(short)); /* 通常是 2 */
16 位 short 的取值范围:
#include <limits.h>
printf("SHRT_MIN = %d\n", SHRT_MIN); /* -32768 */
printf("SHRT_MAX = %d\n", SHRT_MAX); /* 32767 */
short 适合存储范围有限的数据,可以节省内存。在嵌入式系统或大规模数组中,使用 short 代替 int 能将内存占用减半:
/* 存储 10000 个温度值,范围 -50 到 50 */
short temperatures[10000]; /* 20 KB */
int temperatures[10000]; /* 40 KB */
但过度优化类型大小可能导致溢出:
short a = 30000;
short b = 30000;
short c = a + b; /* 溢出!60000 > 32767 */
printf("%d\n", c); /* 输出 -5536(有符号溢出是未定义行为) */
有符号与无符号修饰
默认情况下,short 和 int 都是有符号的(可以表示负数)。加 unsigned 修饰后,只表示非负数,但正数范围扩大一倍:
unsigned int positive = 4000000000U; /* 可以存储大于 INT_MAX 的值 */
printf("UINT_MAX = %u\n", UINT_MAX); /* 4294967295(32 位) */
unsigned short us = 60000; /* 合法:0 到 65535 */
printf("USHRT_MAX = %u\n", USHRT_MAX); /* 65535 */
无符号类型的陷阱:混合运算时,有符号数会被隐式转换为无符号:
unsigned int u = 10;
int s = -5;
if (s < u)
printf("s < u\n"); /* 可能不会输出! */
/* -5 被转换为很大的无符号数 */
整数常量
整数常量的类型由值的大小和后缀决定:
42 /* int */
3000000000 /* 如果超出 int 范围,是 unsigned int 或 long */
42U /* unsigned int */
42L /* long */
42UL /* unsigned long */
42LL /* long long(C99) */
42ULL /* unsigned long long */
没有后缀的小整数默认是 int。如果值超出 int 范围,编译器会依次尝试 unsigned int、long、unsigned long、long long、unsigned long long。
选择指南
| 场景 | 推荐类型 |
|---|---|
| 一般整数计算 | int |
| 明确需要 32 位 | int32_t(<stdint.h>) |
| 明确需要 64 位 | int64_t(<stdint.h>) |
| 内存敏感的大数组 | short(确认范围足够) |
| 计数器、索引(非负) | size_t 或 unsigned int |
| 位运算、标志位 | unsigned int |
#include <stdint.h>
int32_t exact_32bit; /* 保证 32 位,跨平台一致 */
uint16_t flags; /* 16 位无符号,适合位掩码 */
<stdint.h>(C99 新增)提供了定宽整数类型,在需要精确控制大小时(如网络协议、文件格式、硬件寄存器)是最佳选择。
常见错误
整数溢出:
int big = 2147483647;
big = big + 1; /* 溢出!未定义行为 */
printf("%d\n", big); /* 可能输出 -2147483648 */
无符号回绕:
unsigned int u = 0;
u = u - 1; /* 回绕到 UINT_MAX */
printf("%u\n", u); /* 输出 4294967295 */
无符号整数溢出是定义行为(回绕),但有符号整数溢出是未定义行为——后者更危险,因为编译器可能做出任何假设。
格式说明符不匹配:
unsigned int u = 4000000000U;
printf("%d\n", u); /* 错误:%d 对应 int,u 是 unsigned int */
printf("%u\n", u); /* 正确 */
short s = 100;
printf("%d\n", s); /* 正确:short 提升为 int 传递 */