long与long long的区别:64位Windows系统下二者表现一致问题详解
你在64位Windows环境下实测long和long long大小、取值范围一致,属于特定编译环境的正常现象,但二者是C标准定义的完全不同的两种整数类型,核心差异如下:
1 标准定义差异
- C99及之后的C标准明确规定:
long类型的最小存储宽度为32位,long long类型的最小存储宽度为64位。也就是说所有符合标准的编译器,long long一定至少支持64位整数的存储,但long仅强制要求至少32位。 - 32位平台下几乎所有编译器的
long都是32位,取值范围为-2147483648 ~ 2147483647,和int宽度一致,此时和long long的差异非常明显。
2 跨平台实现差异
主流64位操作系统采用两种不同的整数模型,这是两者表现不一致的核心原因:
- LLP64模型(64位Windows默认,MSVC编译器遵循):
int为32位,long为32位,long long为64位,此时long和long long宽度、取值范围完全不同。你测试时得到long为8字节,大概率是使用了MinGW、Clang等第三方编译器,这类编译器在Windows下没有严格遵循LLP64规范,将long实现为64位。 - LP64模型(64位Linux、macOS默认):
int为32位,long为64位,long long也为64位,此时两者宽度、取值范围一致。
3 测试代码说明
你给出的测试代码输出仅代表你当前编译环境的实现,不具备通用性:
#include<stdio.h> int main() { printf("long size: %d\n",sizeof(long)); printf("long long size: %d\n\n",sizeof(long long)); long value1=9223372036854775807; long long value2=9223372036854775807; printf("Max Limits\n"); printf("value1: %li\n",value1); printf("value2: %lli\n\n",value2); //overflow of the range value1++; value2++; printf("value1: %li\n",value1); printf("value2: %lli\n",value2); /* 你的环境输出: long size: 8 long long size: 8 Max Limits value1: 9223372036854775807 value2: 9223372036854775807 value1: -9223372036854775808 value2: -9223372036854775808*/ }
如果你将上述代码用MSVC编译器在64位Windows环境下编译运行,会直接报value1赋值溢出的错误,输出的sizeof(long)结果为4,和你的测试结果完全不同。
4 其他强制差异
即使在两者宽度完全一致的环境下,二者也有不可忽略的区别:
- 整数字面量规则不同:
long类型的整数常量后缀为L/l,long long类型的整数常量后缀为LL/ll,编译器做类型推导时会严格区分二者。 - 类型兼容性不同:二者属于完全独立的两种类型,C++函数重载、格式字符串匹配时都不能通用:比如你用
%li格式符输出long long类型变量,本质属于未定义行为,只是在二者宽度一致的环境下刚好没有触发异常。 - 可移植性风险不同:如果你的代码需要跨平台运行,依赖
long为64位会导致在MSVC编译的64位Windows程序、所有32位平台程序直接出错,而long long可以保证在所有符合C99标准的环境下至少为64位,可移植性远高于long。
最佳实践建议
如果你的业务逻辑需要明确宽度的整数,建议直接使用<stdint.h>头文件中定义的定长整数类型:int64_t(有符号64位整数)、uint64_t(无符号64位整数),可以完全屏蔽不同平台、编译器的实现差异,兼容性最好。
内容的提问来源于stack exchange,提问作者surya sarisa
相关产品推荐
相关产品推荐

