如何在C中确定处理器字长
How to determine processor word length in C?
我在一次采访中遇到了一个问题"如何在不使用C中的sizeof()的情况下确定处理器单词长度?"我认为我给出了错误的答案。
我的代码如下:
int main(){
int num = -1;
int count = 0;
unsigned int num_copy = (unsigned int)num;
while(num_copy >>= 1){
count++;
}
printf("System size of int:%d", (count + 1)/ 8);
return 0;
}
输出答案仅由编译器选项决定。那么,我如何才能得到正确的答案(系统单词长度)?
如果我把这个问题的一部分从"处理器字长"改为"操作系统字长"怎么办?
如@holgac所述,long
数据类型的大小始终与机器的本机单词大小相同:
"单词是机器一次可以处理的数据量"quot;处理器的通用寄存器(GPR)的大小等于其字大小"quot;此外,C型long的大小等于字大小,而int型的大小有时小于字大小"的大小;
--Linux内核开发,Ch 17(第3版,第381页)
然而,正如Thomas Matthews所指出的,这可能不适用于单词长度较小的机器。
要确定编译器上long
的大小,只需使用sizeof(long)
:
int main(void)
{
printf("long is %d bits on this systemn", (int)sizeof(long)*CHAR_BIT);
return 0;
}
另请参阅:
- 什么是CHAR_BIT
我觉得我的强迫症在这里有点发作,结果是:
#include <stdio.h>
#include <limits.h>
#define SIZEOF_CHAR sizeof(char)
#define SIZEOF_INT sizeof(int)
#define SIZEOF_LONG sizeof(long)
#define SIZEOF_POINTER sizeof(void *)
#define NIBBLE_BIT 4
#ifndef CHAR_BIT
#define CHAR_BIT 8 // should have been defined in <limits.h>
#endif
#define INT_BIT (SIZEOF_INT * CHAR_BIT)
#define LONG_BIT (SIZEOF_LONG * CHAR_BIT)
#define POINTER_BIT (SIZEOF_POINTER * CHAR_BIT)
int main(void)
{
char hexchar[SIZEOF_CHAR * 2 + 1],
hexint[SIZEOF_INT * 2 + 1],
hexlong[SIZEOF_LONG * 2 + 1],
hexpointer[SIZEOF_POINTER * 2 + 1];
int strlen_hexchar, strlen_hexint, strlen_hexlong, strlen_hexpointer;
strlen_hexchar = sprintf(hexchar, "%x", (unsigned char)-1);
strlen_hexint = sprintf(hexint, "%x", (unsigned int)-1);
strlen_hexlong = sprintf(hexlong, "%x", (unsigned long)-1l);
strlen_hexpointer = sprintf(hexpointer, "%p", (void*)-1l);
printf("#define SIZEOF_CHAR sizeof(char) // %2dn", SIZEOF_CHAR);
printf("#define SIZEOF_INT sizeof(int) // %2dn", SIZEOF_INT);
printf("#define SIZEOF_LONG sizeof(long) // %2dn", SIZEOF_LONG);
printf("#define SIZEOF_POINTER sizeof(void *) // %2dn", SIZEOF_POINTER);
printf("n");
printf("#define NIBBLE_BIT %-2dn", NIBBLE_BIT);
printf("#ifndef CHAR_BITn");
printf("#define CHAR_BIT %-2d // should have been defined in <limits.h>n", CHAR_BIT);
printf("#endifn");
printf("#define INT_BIT (SIZEOF_INT * CHAR_BIT) // %2dn", INT_BIT);
printf("#define INT_LONG (INT_LONG * CHAR_BIT) // %2dn", LONG_BIT);
printf("#define POINTER_BIT (SIZEOF_POINTER * CHAR_BIT) // %2dn", POINTER_BIT);
printf("n");
printf("nTest setup...n");
printf("n");
printf("char hexchar[CHAR_BIT * SIZEOF_CHAR + 1],n");
printf(" hexint[CHAR_BIT * SIZEOF_INT + 1],n");
printf(" hexlong[CHAR_BIT * SIZEOF_LONG + 1],n");
printf(" hexpointer[CHAR_BIT * SIZEOF_POINTER + 1];n");
printf("int strlen_hexchar, strlen_hexint, strlen_hexlong, strlen_hexpointer;n");
printf("n");
printf("strlen_hexchar = sprintf(hexchar, "%%x", (unsigned char)-1);n// returned %d, hexchar populated with "%s"n",
strlen_hexchar, hexchar);
printf("strlen_hexint = sprintf(hexint, "%%x", (unsigned int)-1);n// returned %d, hexint populated with "%s"n",
strlen_hexint, hexint);
printf("strlen_hexlong = sprintf(hexlong, "%%x", (unsigned long)-1);n// returned %d, hexlong populated with "%s"n",
strlen_hexlong, hexlong);
printf("strlen_hexpointer = sprintf(hexpointer, "%%x", (void*)-1l);n// returned %d, hexpointer populated with "%s"n",
strlen_hexpointer, hexpointer);
printf("nnTest results...n");
printf("n");
if (SIZEOF_CHAR * 2 == strlen_hexchar) {
printf("testing (SIZEOF_CHAR * 2 == strlen_hexchar) [pass]n");
} else {
printf("testing (SIZEOF_CHAR * 2 == strlen_hexchar) [fail]n");
printf(" (%d != $d)n", SIZEOF_CHAR * 2, strlen_hexchar);
}
if (SIZEOF_INT * 2 == strlen_hexint) {
printf("testing (SIZEOF_INT * 2 == strlen_hexint) [pass]n");
} else {
printf("testing (SIZEOF_INT * 2 == strlen_hexint) [fail]n");
printf(" (%d != $d)n", SIZEOF_INT * 2, strlen_hexint);
}
if (SIZEOF_LONG * 2 == strlen_hexlong) {
printf("testing (SIZEOF_LONG * 2 == strlen_hexlong) [pass]n");
} else {
printf("testing (SIZEOF_LONG * 2 == strlen_hexlong) [fail]n");
printf(" (%d != $d)n", SIZEOF_LONG * 2, strlen_hexlong);
}
if (SIZEOF_POINTER * 2 == strlen_hexpointer) {
printf("testing (SIZEOF_POINTER * 2 == strlen_hexpointer) [pass]n");
} else {
printf("testing (SIZEOF_POINTER * 2 == strlen_hexpointer) [fail]n");
printf(" (%d != $d)n", SIZEOF_POINTER * 2, strlen_hexpointer);
}
printf("n");
if (CHAR_BIT == strlen_hexchar * NIBBLE_BIT) {
printf("testing (CHAR_BIT == strlen_hexchar * NIBBLE_BIT) [pass]n");
} else {
printf("testing (CHAR_BIT == strlen_hexchar * NIBBLE_BIT) [fail]n");
printf(" (%d != $d)n", CHAR_BIT, strlen_hexchar * NIBBLE_BIT);
}
if (INT_BIT == strlen_hexint * NIBBLE_BIT) {
printf("testing (INT_BIT == strlen_hexint * NIBBLE_BIT) [pass]n");
} else {
printf("testing (INT_BIT == strlen_hexint * NIBBLE_BIT) [fail]n");
printf(" (%d != $d)n", INT_BIT, strlen_hexint * NIBBLE_BIT);
}
if (LONG_BIT == strlen_hexlong * NIBBLE_BIT) {
printf("testing (LONG_BIT == strlen_hexlong * NIBBLE_BIT) [pass]n");
} else {
printf("testing (LONG_BIT == strlen_hexlong * NIBBLE_BIT) [fail]n");
printf(" (%d != $d)n", LONG_BIT, strlen_hexlong * NIBBLE_BIT);
}
if (POINTER_BIT == strlen_hexpointer * 4) {
printf("testing (POINTER_BIT == strlen_hexpointer * NIBBLE_BIT) [pass]n");
} else {
printf("testing (POINTER_BIT == strlen_hexpointer * NIBBLE_BIT) [fail]n");
printf(" (%d != $d)n", POINTER_BIT, strlen_hexpointer * NIBBLE_BIT);
}
printf("n");
if ((int)(SIZEOF_POINTER * CHAR_BIT) == strlen_hexpointer * NIBBLE_BIT) {
printf("testing ((int)(SIZEOF_POINTER * CHAR_BIT) == strlen_hexpointer * NIBBLE_BIT) [pass]n");
} else {
printf("testing ((int)(SIZEOF_POINTER * CHAR_BIT) == strlen_hexpointer * NIBBLE_BIT) [fail]n");
printf(" (%d != %d)n", (int)(SIZEOF_POINTER * CHAR_BIT), strlen_hexpointer * NIBBLE_BIT);
}
printf("nConclusion: this machine word is %d bytes and %d bitsn", SIZEOF_POINTER * 8 / CHAR_BIT, strlen_hexpointer * NIBBLE_BIT);
if ((int)(SIZEOF_POINTER * CHAR_BIT) != strlen_hexpointer * NIBBLE_BIT) {
printf(" * however this conclusion did not pass the (int)(SIZEOF_POINTER * 8 / CHAR_BIT) == strlen_hexpointer * NIBBLE_BIT) testn");
}
return 0;
}
此代码的输出在我的机器上显示以下内容:
$ sizeofword.exe # from mingw32 shell on windows7
#define SIZEOF_CHAR sizeof(char) // 1
#define SIZEOF_INT sizeof(int) // 4
#define SIZEOF_LONG sizeof(long) // 4
#define SIZEOF_POINTER sizeof(void *) // 4
#define NIBBLE_BIT 4
#ifndef CHAR_BIT
#define CHAR_BIT 8 // should have been defined in <limits.h>
#endif
#define INT_BIT (SIZEOF_INT * CHAR_BIT) // 32
#define INT_LONG (INT_LONG * CHAR_BIT) // 32
#define POINTER_BIT (SIZEOF_POINTER * CHAR_BIT) // 32
Test setup...
char hexchar[CHAR_BIT * SIZEOF_CHAR + 1],
hexint[CHAR_BIT * SIZEOF_INT + 1],
hexlong[CHAR_BIT * SIZEOF_LONG + 1],
hexpointer[CHAR_BIT * SIZEOF_POINTER + 1];
int strlen_hexchar, strlen_hexint, strlen_hexlong, strlen_hexpointer;
strlen_hexchar = sprintf(hexchar, "%x", (unsigned char)-1);
// returned 2, hexchar populated with "ff"
strlen_hexint = sprintf(hexint, "%x", (unsigned int)-1);
// returned 8, hexint populated with "ffffffff"
strlen_hexlong = sprintf(hexlong, "%x", (unsigned long)-1);
// returned 8, hexlong populated with "ffffffff"
strlen_hexpointer = sprintf(hexpointer, "%x", (void*)-1l);
// returned 8, hexpointer populated with "FFFFFFFF"
Test results...
testing (SIZEOF_CHAR * 2 == strlen_hexchar) [pass]
testing (SIZEOF_INT * 2 == strlen_hexint) [pass]
testing (SIZEOF_LONG * 2 == strlen_hexlong) [pass]
testing (SIZEOF_POINTER * 2 == strlen_hexpointer) [pass]
testing (CHAR_BIT == strlen_hexchar * NIBBLE_BIT) [pass]
testing (INT_BIT == strlen_hexint * NIBBLE_BIT) [pass]
testing (LONG_BIT == strlen_hexlong * NIBBLE_BIT) [pass]
testing (POINTER_BIT == strlen_hexpointer * NIBBLE_BIT) [pass]
testing ((int)(SIZEOF_POINTER * CHAR_BIT) == strlen_hexpointer * NIBBLE_BIT) [pass]
Conclusion: this machine word is 4 bytes and 32 bits
不允许sizeof
吗?
此外,还有一个稍微改进的实现(不需要拷贝,循环运行次数更少,而且不需要划分):
int main(){
int num = 1;
int count = 0;
while(num <<= 8){
count++;
}
printf("System size of int:%d", count+1);
return 0;
}
作为一个面试问题,在直C中唯一正确的方法是使用条件编译。条件编译允许针对软件运行的各种平台不同地定义单词大小,或者以某种方式识别单词大小,从而可以从数据库中获得正确的大小。由于公司知道产品将在哪些平台上运行,或者他们愿意支持哪些平台,因此可以在编译或运行时选择该平台,并因此选择正确的单词大小。
找出单词大小的任何其他方式将是特定于平台/系统的代码或启发式方法。一种可能的启发式方法是使用指针的大小来表示机器单词的大小。
word_size = sizeof(void *);
考虑到这是一种启发式方法,它会在某些平台上失败。
- #定义c-预处理器常量..我做错了什么
- 预处理器:插入结构名称中的前一个行号
- 如何在c++中实现处理器调度模拟器
- 当套接字连接断开时检测C/C++Unix
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- C/C++预处理器是否可以检测一些编译器选项
- mbed 套接字连接需要很长时间
- 为什么 Windows udp 接收套接字上的超时总是比 SO_RCVTIMEO 设置的长 500 毫秒
- 最长的常见子字错误结果
- 通过套接字C++发送长字符串
- 使用C预处理器在结构字段上进行迭代
- 如何在C中确定处理器字长
- 为什么开发人员在多线程代码的读/写过程中锁定字长数据
- c位字段在结构中具有长int的奇怪行为
- 对齐和字长
- 具有非八位对齐子字段的96位长位域
- C/ c++预处理器中的宏参数字符串化为宽字符串字面值
- 频率字长,程序只打开cmd,但不做任何事,c++
- 计算机中的字长与整型或长有什么关系?