gpt4 book ai didi

c - stdint.h 中的无符号整数类型对可以存储的内容没有限制?

转载 作者:太空狗 更新时间:2023-10-29 15:58:36 28 4
gpt4 key购买 nike

对于 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

所以问题是,其中无符号整数的用途或值(value)是什么stdint.h 似乎我可以使用 64 位位域或数组八个无符号字符或任何足够大的内存块?值(value)在哪里这里?便携性?

/************** COMMENT AFTER SEEING GREAT ANSWERS BELOW ************/

下面的人给出的很好的答案对我有启发,我看到 stdint.h 类型跨平台可移植,它们允许更大范围的积极整数值。存储在变量中的数据的解释是我需要处理的事情,而不是期望我的编译器或调试器神秘地或者神奇地知道我们在这里只使用正数。

实际上,我认为最安全的做法是坚持使用 uint32_t,它位于C99 标准,然后执行此操作以获得正确的正值:

 a_big_positive_number = (uint32_t) labs( strtol( argv[1], (char **)NULL, 10) );

为了 super 安全,我应该在接受之前自己检查 argv[1]它。谁知道呢,可能是负数,也可能是垃圾数据。

最佳答案

有符号整数类型到无符号整数类型的转换完全在 C 中定义,并且隐式发生在 a_big_positive_number = strtol(...); 中,就好像您已经编写了 a_big_positive_number = ( uint64_t) strtol(…);.

C99 标准的 6.3.1.3:2 条款适用:

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

(在从另一种类型转换的上下文中)

6.5.16.1:2 子句表示转换发生在赋值时:

In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.

关于uint64_t的值,我不确定你问的是什么。类型 uint64_t 是一个恰好 64 位的无符号类型。 unsigned long long bf:64; 位域不能保证在内存中只占用 64 位,八个无符号字符的数组也不能保证(运算符不能直接作用于后者) ).

关于c - stdint.h 中的无符号整数类型对可以存储的内容没有限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18046218/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com