整型数据概述
整型数据是C语言中最基础的数据类型之一,用于表示整数。整数是不带小数部分的数值,可以是正数、负数或零。在计算机中,整型数据以二进制形式存储,其表示范围和精度由具体的整型类型决定。
整型类型分类
基本整型关键字
C语言提供了多种整型类型,以适应不同的数值范围需求:
1.int(整型)
- 最常用的整型类型
- 一般占用4字节(32位系统)
- C语言标准规定至少占用2字节
- 数值范围:通常为-2,147,483,648到2,147,483,647
2.short(短整型)
- 占用空间小于或等于int
- 一般占用2字节
- 数值范围:通常为-32,768到32,767
3.long(长整型)
- 占用空间大于或等于int
- 一般占用4字节(32位系统)或8字节(64位系统)
- C语言标准规定至少占用4字节
4.long long(长长整型)
- C99标准引入
- 至少占用8字节
- 数值范围:至少-9,223,372,036,854,775,808到9,223,372,036,854,775,807
示例
c
// 各种整型类型示例
#include <stdio.h>
int main() {
int standard_int = 100;
short short_int = 200;
long long_int = 300L; // L后缀表示long类型
long long very_long = 400LL; // LL后缀表示long long类型
printf("int: %d\n", standard_int);
printf("short: %hd\n", short_int); // %hd用于short
printf("long: %ld\n", long_int); // %ld用于long
printf("long long: %lld\n", very_long); // %lld用于long long
return 0;
}
有符号与无符号整型
整型可以进一步分为有符号(signed)和无符号(unsigned)两种类型:
有符号整型(signed)
- 可以表示正数、负数和零
- signed关键字通常可以省略(默认就是signed)
- 最高位作为符号位(0表示正数,1表示负数)
无符号整型(unsigned)
- 只能表示非负数(0和正数)
- 所有位都用于表示数值大小
- 相同位数的无符号类型比有符号类型能表示的最大正数大一倍
示例
c
#include <stdio.h>
#include <limits.h>
int main() {
// 有符号整型示例
signed int signed_num = -100; // signed可省略
int another_signed = -50; // 默认就是signed
// 无符号整型示例
unsigned int unsigned_num = 200;
unsigned long big_positive = 4294967295U; // U后缀表示unsigned
printf("有符号整数: %d\n", signed_num);
printf("无符号整数: %u\n", unsigned_num);
printf("无符号长整型最大值: %lu\n", big_positive);
// 查看各种类型的范围
printf("\n各类型数值范围:\n");
printf("int范围: %d 到 %d\n", INT_MIN, INT_MAX);
printf("unsigned int范围: 0 到 %u\n", UINT_MAX);
printf("short范围: %d 到 %d\n", SHRT_MIN, SHRT_MAX);
return 0;
}
有符号与无符号的区别
| 特性 | 有符号整型(signed) | 无符号整型(unsigned) |
|---|---|---|
| 符号位 | 有(最高位) | 无 |
| 可表示负数 | 可以 | 不可以 |
| 数值范围(32位) | − 2 31 -2^{31} −231 到 2 31 − 1 2^{31}-1 231−1 | 0 到 2 32 − 1 2^{32}-1 232−1 |
| 溢出行为 | 可能产生未定义行为 | 采用模运算(循环) |
| 默认类型 | 大多数整型默认有符号 | 需要显式声明 |
整型在内存中存储原理
二进制表示与补码系统
计算机内部使用二进制补码形式存储整型数据。补码系统有以下优点:
- 统一了正数和负数的加减运算
- 消除了+0和-0的歧义
- 简化了硬件设计
原码、反码和补码
1.原码 :最高位表示符号,其余位表示绝对值的二进制
2.反码 :正数的反码与原码相同;负数的反码是对原码除符号位外各位取反
3.补码 :正数的补码与原码相同;负数的补码是反码加1

补码计算过程:
- 正数:原码 = 反码 = 补码
- 负数:
- 先求绝对值的二进制(原码)
- 除符号位外各位取反(反码)
- 反码加1得到补码
示例:
c
// 补码示例:以8位有符号char类型为例
#include <stdio.h>
void print_binary(char num) {
for (int i = 7; i >= 0; i--) {
printf("%d", (num >> i) & 1);
if (i == 4) printf(" "); // 添加空格提高可读性
}
}
int main() {
char positive = 5; // 0000 0101
char negative = -5; // 1111 1011
printf("+5 的原码/反码/补码: ");
print_binary(positive);
printf("\n");
printf("-5 的存储形式(补码): ");
print_binary(negative);
printf("\n");
// 验证补码性质
printf("\n验证补码性质:\n");
printf("5 + (-5) = %d\n", positive + negative); // 应该为0
printf("二进制计算: 00000101 + 11111011 = 00000000\n");
return 0;
}
数值溢出与循环计数
当赋给整型变量的值超出其表示范围时,会发生数值溢出:
无符号整型溢出
无符号整型采用模运算(循环计数):
c
#include <stdio.h>
int main() {
unsigned int max = 4294967295U; // 32位无符号最大值
printf("无符号整型溢出示例:\n");
printf("最大值: %u\n", max);
printf("最大值 + 1: %u\n", max + 1); // 变为0
printf("0 - 1: %u\n", 0U - 1); // 变为最大值
// 计算 -5 在无符号整型中的表示
unsigned int b = -5;
printf("\n-5 在无符号整型中: %u\n", b);
printf("解释: 0 - 5 = 4294967291 (2³² - 5)\n");
return 0;
}
有符号整型溢出
有符号整型溢出是未定义行为(编译器相关):
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("有符号整型溢出(未定义行为):\n");
int max_int = INT_MAX;
int min_int = INT_MIN;
printf("INT_MAX: %d\n", max_int);
printf("INT_MAX + 1: %d (实际行为取决于编译器)\n", max_int + 1);
printf("\nINT_MIN: %d\n", min_int);
printf("INT_MIN - 1: %d (实际行为取决于编译器)\n", min_int - 1);
return 0;
}
重要提示:在实际编程中,应尽量避免整型溢出,特别是对于有符号整型,因为其溢出行为是未定义的,可能导致不可预测的结果。
输入输出与格式控制符
常用格式控制符
| 格式控制符 | 适用类型 | 说明 |
|---|---|---|
| %d | int | 有符号十进制整数 |
| %u | unsigned int | 无符号十进制整数 |
| %ld | long | 有符号十进制长整数 |
| %lu | unsigned long | 无符号十进制长整数 |
| %lld | long long | 有符号十进制长长整数 |
| %llu | unsigned long long | 无符号十进制长长整数 |
| %hd | short | 有符号十进制短整数 |
| %hu | unsigned short | 无符号十进制短整数 |
| %x, %X | 整型 | 十六进制整数(小写/大写) |
| %o | 整型 | 八进制整数 |
输入输出示例
c
#include <stdio.h>
int main() {
int a;
unsigned int b;
long c;
unsigned long d;
// 输入示例
printf("请输入一个有符号整数: ");
scanf("%d", &a);
printf("请输入一个无符号整数: ");
scanf("%u", &b);
printf("请输入一个有符号长整数: ");
scanf("%ld", &c);
printf("请输入一个无符号长整数: ");
scanf("%lu", &d);
// 输出示例
printf("\n输入结果:\n");
printf("有符号整数: %d\n", a);
printf("无符号整数: %u\n", b);
printf("有符号长整数: %ld\n", c);
printf("无符号长整数: %lu\n", d);
// 不同进制输出
printf("\n不同进制表示:\n");
printf("%d 的八进制: %o\n", a, a);
printf("%d 的十六进制: %x (小写) 或 %X (大写)\n", a, a, a);
// 控制输出宽度和填充
printf("\n格式化输出:\n");
printf("默认: %d\n", a);
printf("宽度10: %10d\n", a); // 宽度10,右对齐
printf("宽度10,左对齐: %-10d|\n", a); // 宽度10,左对齐
printf("宽度10,前导0: %010d\n", a); // 宽度10,前导0填充
return 0;
}
进制转换
十进制转N进制(短除法)
将十进制数转换为N进制数的通用方法:
算法步骤:
- 用十进制数除以N,记录余数
- 用商继续除以N,记录余数
- 重复步骤2,直到商为0
- 将余数逆序排列,得到N进制表示


N进制转十进制(按权展开)
将N进制数转换为十进制数的通用方法
算法原理:
确定数据的位数,以及每个位上的数值,规定整数部分的最低位为第0位。
以N为底数,处于第多少位作为指数进行幂运算,然后乘上该位数值,对于每个位重复此操作,最终累加求和,得到转换后的十进制。

C语言中的进制表示
在C语言中,可以直接使用不同进制的字面量:
c
#include <stdio.h>
int main() {
// 十进制(默认)
int decimal = 3456;
// 八进制(以0开头)
int octal = 06600; // 八进制的6600 = 十进制的3456
// 十六进制(以0x或0X开头)
int hex1 = 0xD80; // 十六进制的D80
int hex2 = 0xd80; // 小写也可以
// 二进制(C语言标准不支持二进制字面量,但有些编译器扩展支持)
// int binary = 0b11011000000; // 某些编译器支持
printf("十进制表示: %d\n", decimal);
printf("八进制表示: %o (十进制值: %d)\n", octal, octal);
printf("十六进制表示: %x (十进制值: %d)\n", hex1, hex1);
// 使用不同格式输出同一个数
printf("\n同一数值的不同进制输出:\n");
printf("十进制: %d\n", decimal);
printf("八进制: %o\n", decimal);
printf("十六进制(小写): %x\n", decimal);
printf("十六进制(大写): %X\n", decimal);
// 显示前缀
printf("\n带前缀的输出:\n");
printf("八进制: %#o\n", decimal); // 输出: 06600
printf("十六进制: %#x\n", decimal); // 输出: 0xd80
printf("十六进制(大写): %#X\n", decimal); // 输出: 0XD80
return 0;
}
整型的使用建议
选择合适的类型
c
// 根据数据范围选择类型
#include <stdint.h> // 提供固定宽度整数类型
int main() {
// 明确范围时使用固定宽度类型
int8_t small_num = 100; // 确切占用1字节
int16_t medium_num = 30000; // 确切占用2字节
int32_t large_num = 2000000; // 确切占用4字节
int64_t huge_num = 9000000000; // 确切占用8字节
// 无符号固定宽度类型
uint8_t byte_data = 255;
uint32_t ip_address = 0xC0A80101; // 192.168.1.1
return 0;
}
避免有符号和无符号混合运算
c
#include <stdio.h>
int main() {
unsigned int u = 10;
int s = -5;
printf("有符号与无符号混合运算:\n");
printf("u + s = %u (可能不是期望的结果)\n", u + s);
// 安全的方法:统一类型后再运算
if (s < 0) {
printf("安全方法: s是负数,不能直接与无符号数相加\n");
} else {
unsigned int safe_sum = u + (unsigned int)s;
printf("安全求和: %u\n", safe_sum);
}
return 0;
}
检查溢出
c
#include <stdio.h>
#include <limits.h>
// 安全加法函数
int safe_add(int a, int b) {
if (b > 0 && a > INT_MAX - b) {
printf("警告: 加法可能溢出\n");
return INT_MAX;
}
if (b < 0 && a < INT_MIN - b) {
printf("警告: 加法可能下溢\n");
return INT_MIN;
}
return a + b;
}
int main() {
int a = INT_MAX - 5;
int b = 10;
int result = safe_add(a, b);
printf("%d + %d = %d\n", a, b, result);
return 0;
}