不用 sizeof 判断操作系统是 32 还是 64 位

1.背景

2018 上半年折腾了一回,想换个后台开发岗锻炼一下自己。我在腾讯内部转岗遇到了这道面试题,特此记录下来。

2.问题

我们知道在 C/C++ 中使用运算符 sizeof 计算指针变量的大小,如果返回值为 4 字节则是 32 位,如果返回 8 字节,则表示 64 位系统。

现在要求不使用 sizeof 如何判断操作系统是 32 位还是 64 位。

3.解法

3.1 解法一:整型最大值溢出

我们知道 C/C++中,32 位系统下编译生成的程序,整型数值默认取值范围是 − 2 31 -2^{31} 231 2 31 − 1 2^{31}-1 2311,加上数值后缀 L,表示长整型,取值范围也是 − 2 31 -2^{31} 231 2 31 − 1 2^{31}-1 2311,加上 LL 表示长长整型数值,取值范围是 − 2 63 -2^{63} 263 2 63 − 1 2^{63}-1 2631

64 位系统下编译生成的 64 位程序(为什么指明说 64 位的程序,因为 64 系统下也可以编译生成32的位的程序),整型数值默认取值范围是 − 2 31 -2^{31} 231 2 31 − 1 2^{31}-1 2311,加上数值后缀 L,表示长整型,取值范围也是 − 2 63 -2^{63} 263 2 63 − 1 2^{63}-1 2631,加上 LL 表示长长整型数值,取值范围是 − 2 63 -2^{63} 263 2 63 − 1 2^{63}-1 2631

所以根据数值后缀 L 可以判断系统是 32 位还是 64 位,实际上我们是利用整型最大值是否溢出情况来做判断。

#include <iostream>
using namespace std;

int main() {
	long ldTmp = 1L<<32;
	cout << "sizeof(long):" << sizeof(long) << endl;
	cout << "ldTmp:" << ldTmp << endl;
	if(ldTmp) {
		cout<<"64 bits"<<endl;
	} else {
		cout<<"32 bits"<<endl;
	}
}

使用g++ -m64 main.cpp -o a64.out生成 64 位程序输出结果为:

sizeof(long):8
ldTmp:4294967296
64 bits

使用g++ -m32 main.cpp -o a32.out生成32位程序输出结果为:

sizeof(long):4
ldTmp:0
32 bits

3.2 解法二:__WORDSIZE

Linux 环境下,可以根据 GNU C 库的头文件 wordsize.h 中定义的宏 __WORDSIZE 来判断。wordsize.h 路径一般为 /usr/include/bits/wordsize.h,其内容如下:

/* Determine the wordsize from the preprocessor defines.  */

#if defined __x86_64__
# define __WORDSIZE     64
# define __WORDSIZE_COMPAT32    1
#else
# define __WORDSIZE     32
#endif

判断代码如下:

#include <bits/wordsize.h>

#include <iostream>
using namespace std;

int main() {
#if __WORDSIZE == 64
	cout << "64bits" << endl;
#else
	cout << "32bits" << endl;
#endif
}

类似的方法,在 limits.h 头文件中,包含了头文件 wordsize.h 后,根据 __WORDSIZE 做了如下相关宏定义:

/* Maximum value an `unsigned long int' can hold.  (Minimum is 0.)  */
#  if __WORDSIZE == 64
#   define ULONG_MAX    18446744073709551615UL
#  else
#   define ULONG_MAX    4294967295UL
#  endif

所以,根据如下代码也可以判断程序是 32 位还是 64 位。

#include <limits.h>

#include <iostream>
using namespace std;

int main() {
#if ULONG_MAX==0xFFFFFFFFFFFFFFFFUL
    cout << "64bits" << endl;
#else
    cout << "32bits" << endl;
#endif
}

3.3 解法三:指针变量位宽

根据栈指针变量宽度来判断,感谢腾讯 blitzhong 同学的提示。对指针变量地址相减时,须将其转换为 char* 或无符号长整型(unsigned long),否则相减的结果为 1,表示地址间隔内存放元素的个数。

#include <iostream>
using namespace std;

int main() {
	void* a;
	void* b;
	int scope = (char*)&a - (char*)&b;
	cout << "&a:" << &a << endl;
	cout << "&b:" << &b << endl;
	cout << "scope:" << scope << endl;
	if(scope==8) {
		cout << "64bits" << endl;
	} else {
		cout << "32bits" << endl;
	}
}

使用g++ -m64 main.cpp -o a64.out编译执行输出:

&a:0x7fffcc84b650
&b:0x7fffcc84b648
scope:8
64bits

使用g++ -m32 main.cpp -o a32.out编译执行输出:

&a:0xffbb42e8
&b:0xffbb42e4
scope:4
32bits

如果网友有其他方法,也请留言告知,万分感谢!


参考文献

Determining 32 vs 64 bit in C++ - Stack Overflow

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值