long unsigned 并不是一个独立的关键字,而是两个类型修饰符 long 和 unsigned 的组合,它用来声明一个无符号的长整型变量。

(图片来源网络,侵删)
核心概念解析
要理解 long unsigned,我们需要先拆解它的两个组成部分:
a. long (长整型)
long 是一个类型修饰符,用来告诉编译器这个变量是一个“长整型”,它的主要目的是为了提供比普通 int 更大的存储空间,从而表示更大的整数范围。
int: 基本整型,其大小(通常是 16 位或 32 位)由编译器和平台决定。long: 长整型,其大小通常不小于int,在大多数现代系统(如 64 位 Windows, Linux, macOS)上,long的大小是 32 位(4 字节),与int相同,但在一些旧系统或特定架构上,long可能是 64 位的。
b. unsigned (无符号)
unsigned 是一个类型修饰符,用来声明变量只能存储非负整数(即 0 和正整数),它将整个数值范围都用来表示正数,因此其表示的最大值是有符号同类型变量的两倍。
- 有符号变量: 使用最高位(MSB)作为符号位(0 为正,1 为负),一个 8 位有符号
char的范围是 -128 到 127。 - 无符号变量: 所有位都用来表示数值,一个 8 位无符号
char的范围是 0 到 255。
long unsigned 的含义
当 long 和 unsigned 组合在一起时,long unsigned 就定义了一个无符号的长整型。

(图片来源网络,侵删)
- 关键字组合: 在 C 语言中,
long unsigned和unsigned long是完全等价的。unsigned long是更常见、更推荐的写法,因为它更符合“类型在前,修饰符在后”的逻辑顺序。 - 存储大小:
long unsigned的大小与long相同,在 32 位和 64 位系统上,它通常是 32 位(4 字节)。 - 表示范围: 因为是无符号的,所以它只能表示 0 和正数,其范围是 0 到 2³² - 1(即 0 到 4,294,967,295)。
与其他整型的比较
为了更好地理解,我们来看一个在 32 位和 64 位系统上常见的整型大小和范围对比表:
| 类型 | 大小 (字节) | 范围 (有符号) | 范围 (无符号) |
|---|---|---|---|
char |
1 | -128 到 127 | 0 到 255 |
short |
2 | -32,768 到 32,767 | 0 到 65,535 |
int |
4 | -2,147,483,648 到 2,147,483,647 | 0 到 4,294,967,295 |
long |
4 | -2,147,483,648 到 2,147,483,647 | 0 到 4,294,967,295 |
long long |
8 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 | 0 到 18,446,744,073,709,551,615 |
关键观察点:
long和int: 在现代 32/64 位系统上,它们的大小和范围通常是相同的,不要想当然地认为long一定比int大。long unsignedvsunsigned long: 它们是同一个类型,完全等价。long unsignedvsunsigned int: 在大多数系统上,它们的大小和范围也是相同的,如果明确需要 32 位无符号整数,两者都可以用,但unsigned long的语义更清晰。long long: 如果你需要比long更大的范围(64 位整数),应该使用long long或unsigned long long。
代码示例
下面是一个简单的 C 语言程序,演示了 long unsigned 的用法。
#include <stdio.h>
#include <limits.h> // 包含各种整型限制的宏定义
int main() {
// 声明一个 long unsigned 类型的变量
// 推荐使用 unsigned long,但 long unsigned 也可以
unsigned long my_large_number = 4294967295UL;
long unsigned another_number = 12345;
// 打印变量的大小和值
printf("Size of 'unsigned long' (long unsigned): %zu bytes\n", sizeof(unsigned long));
printf("Value of my_large_number: %lu\n", my_large_number);
printf("Value of another_number: %lu\n", another_number);
// 打印其最大值和最小值
// %lu 是打印 unsigned long 类型变量的格式说明符
printf("Maximum value of unsigned long: %lu\n", ULONG_MAX);
printf("Minimum value of unsigned long: 0\n");
// 演示溢出
my_large_number = my_large_number + 1;
printf("After overflow (4294967295 + 1): %lu\n", my_large_number); // 会回绕到 0
return 0;
}
代码解释:

(图片来源网络,侵删)
#include <limits.h>: 这个头文件定义了各种整型的极限值,ULONG_MAX(unsigned long的最大值)。unsigned long my_large_number = 4294967295UL;:- 我们声明了一个
unsigned long变量my_large_number。 - 我们给它赋值为
4294967295,这是 32 位无符号整数的最大值。 UL后缀: 这是一个非常重要的细节。U表示这是一个无符号整数字面量,L表示这是一个长整型字面量,加上UL可以确保编译器将这个数字正确地解释为unsigned long类型,而不是int或long。
- 我们声明了一个
printf("%lu", ...):%lu是printf函数用来打印unsigned long类型变量的格式说明符。sizeof(unsigned long):sizeof操作符返回变量或类型在内存中所占的字节数,这可以帮助你确认在你的特定编译器和平台上,unsigned long的大小。- 溢出演示: 无符号整数的算术运算是“模运算”(modulo arithmetic),当结果超过了最大值时,它会从 0 开始重新计数。
4294967295 + 1的结果是4294967296,但它超出了unsigned long的范围,所以会“回绕”到0。
总结与最佳实践
long unsigned等价于unsigned long: 推荐使用unsigned long,因为它更清晰、更常见。- 大小不保证:
long的大小依赖于平台,虽然通常是 32 位,但如果你需要精确大小的整数(如 32 位或 64 位),应该使用 C99 引入的stdint.h头文件中的固定宽度整数类型。- 对于 32 位无符号整数:
uint32_t - 对于 64 位无符号整数:
uint64_t
- 对于 32 位无符号整数:
- 使用后缀: 在给
long或unsigned long类型的变量赋值时,最好使用L或UL后缀,以避免意外的类型转换和警告。12345UL。 - 何时使用:
- 当你需要存储一个很大的、非负的整数,并且确定它的大小在
unsigned long的范围内时。 - 当处理内存地址、文件大小、计时器计数值等非负的大整数时,
unsigned long是一个很好的选择。
- 当你需要存储一个很大的、非负的整数,并且确定它的大小在
long unsigned(或 unsigned long)就是你用来表示“很大的非负数”的标准工具之一。
