对于 stdint.h,我必须参考此页面:
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdint.h.html
我完全惊讶地发现我可以在定义为 uint64_t 类型的变量中存储一个负数。我脑子里有一个想法,即无符号数据类型总是一个正数,如果我试图在其中存储一个负数,我会得到一个错误。以下让我感到惊讶:
#define _XOPEN_SOURCE 600
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
int main ( int argc, char *argv[] ) {
uint64_t a_big_positive_number;
unsigned long another_big_positive_number;
if ( argc < 2 ) {
printf ( "usage : %s some_integer\n", argv[0] );
exit( EXIT_FAILURE );
}
a_big_positive_number = 0;
a_big_positive_number = strtol( argv[1], (char **)NULL, 10);
fprintf ( stderr, "%i : %s\n", errno, strerror(errno) );
another_big_positive_number = a_big_positive_number;
fprintf ( stderr, "%i : %s\n", errno, strerror(errno) );
return ( EXIT_SUCCESS );
}
当我用完整的 C99 迂腐标志编译它时,我得到了一个二进制文件,它做了以下令人惊讶的事情:
$ ./boffo -12345
0 : Error 0
0 : Error 0
真的吗 ?
我在调试器中运行它,我看到确实是的,uint64_t 非常适合有一个负数并且接近我可以告诉我可以在那里填充我想要的任何 64 位:
(dbx) run -12345
Running: boffo -12345
(process id 16270)
stopped in main at line 15 in file "boffo.c"
15 if ( argc < 2 ) {
(dbx) step
stopped in main at line 20 in file "boffo.c"
20 a_big_positive_number = 0;
首先,我想看看这个变量在内存中的位置(我猜在堆栈上):
(dbx) print &a_big_positive_number
&a_big_positive_number = 0xffffffff7ffff620
太好了...现在获取 argv[1] 输入字符串并将其转换为长整数:
(dbx) step
stopped in main at line 22 in file "boffo.c"
22 a_big_positive_number = strtol( argv[1], (char **)NULL, 10);
(dbx) step
stopped in main at line 23 in file "boffo.c"
23 fprintf ( stderr, "%i : %s\n", errno, strerror(errno) );
我们现在在那个地址的内存中有什么?
(dbx) x &a_big_positive_number / 4 x
0xffffffff7ffff620: 0xffff 0xffff 0xffff 0xcfc7
无符号 64 位数据类型中的负数。完全没有错误!
(dbx) cont
Reading libc_psr.so.1
0 : Error 0
0 : Error 0
execution completed, exit code is 0
(dbx) quit
所以问题是,当我似乎可以使用 64 位位域或八个无符号字符的数组或任何足够大的内存块时,stdint.h 中无符号整数的用途或价值是什么?这里的价值在哪里?便携性?
/************** COMMENT AFTER SEEING GREAT ANSWERS BELOW ************/
下面的人的好答案教育了我,我看到 stdint.h 类型可以跨平台移植,它们允许更大范围的正整数值。存储在变量中的数据的解释是我要处理的事情,而不是期望我的编译器或调试器神秘地或神奇地知道我们在这里只使用正数。
实际上,我认为最安全的做法是坚持使用 C99 标准中的 uint32_t ,然后这样做以获得正确的正值:
a_big_positive_number = (uint32_t) labs( strtol( argv[1], (char **)NULL, 10) );
为了超级“腰带和吊带”安全,我应该在接受之前自己检查 argv[1]。谁知道呢,可能是负数,也可能是垃圾数据。