我试图通过这种方式将一个带符号的十六进制数转换为WORD,DWORD和QWORD:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
int main(void) {
printf("WORD=%d\n", (int16_t) strtol("F123", NULL, 16));
printf("DWORD=%d\n", (int32_t) strtol("FFFFF123", NULL, 16));
printf("QWORD=%lld\n", (int64_t) strtol("FFFFFFFFFFFFF123", NULL, 16));
return 0;
}
但它返回以下内容:
WORD=-3805
DWORD=2147483647
QWORD=2147483647
但为什么DWORD和QWORD演员也没有返回-3805
?
我的意思是:存储在DWORD中的0xFFFFF123
将包含十进制的-3805
值,而不是2147483647
预期产出:
WORD=-3805
DWORD=-3805
QWORD=-3805
你有一个按位替代方法吗?
答案 0 :(得分:4)
如果long int有32位,则0xFFFFF123超出long int的范围,因此strtol()返回LONG_MAX(在我们的例子中为0x7FFFFFFF = 2147483647)。
使用strtoull()将字符串转换为至少64位的无符号整数,并在继续之前检查错误。
要打印具有指定位大小的整数,请使用以下内容:
printf("foo=%"PRIu32"\n",(uint32_t) foo);
更好的方法:
#include <stdio.h>
#include <stdlib.h>
#define __STDC_FORMAT_MACROS //we need that for PRI[u]8/16/32 format strings
#include <inttypes.h>
#include <errno.h>
void error_exit(void)
{
perror("ups");
exit(EXIT_FAILURE);
}
int main(void)
{
unsigned long long temp;
errno=0;
temp = strtoull("FFFFF123", NULL, 16);
if(errno)
{
error_exit();
}
printf("DWORD=%"PRId32"\n", (int32_t) temp );
errno=0;
temp = strtoull("FFFFFFFFFFFFF123", NULL, 16);
if(errno)
{
error_exit();
}
printf("QWORD=%"PRId64"\n", (int64_t) temp );
return EXIT_SUCCESS;
}
答案 1 :(得分:3)
strtol
不假设两个补码输入。为了将某些东西视为否定,您必须使用减号。例如"-F123"
。这就是为什么第2和第3行不给出负输出的原因。
如果是第一行,您的预期输出大多是偶然的。由于在strtol
调用之后,您将十六进制值0xF123
向下转换为int16_t
。它不适合int16_t
,因此会转换为负值。
一些错误:
strtol("FFFFFFFFFFFFF123")
无法保存结果,long
将无效。您应该使用strtoll
。PRId
,例如:printf("WORD=%" PRId16 "\n", my_int16_t);
strtoul
等函数,然后转换为签名类型。答案 2 :(得分:0)
此代码中存在一些错误。
第一行中的主要问题是您无法将长整数转换为int16_t
,因为int16_t
的大小小于long int
。
此外,您应使用PRId16
说明符打印int16_t
。
第二行导致打印LONG_MAX
,因为0xFFFFF123
超出了长整数的范围。
第三行与第二行具有相同的问题,FFFFFFFFFFFFF123
甚至超出范围并将其转换为64位值无济于事。
另外,您需要使用迈克尔已经说明的%lld
或PRId64
进行打印。
答案 3 :(得分:0)
问题是strtol
的最大输入是0x7fffffff(或LONG_MAX)。如果要转换的数字超出范围,errno
已设置且结果为LONG_MAX
或LONG_MIN
,请参阅strtol documentation了解详情。
插图:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main() {
int x = strtol("7f000000", NULL, 16); // in range
printf ("x = %d, errno = %d\n", errno);
x = strtol("F0000000", NULL, 16); // out of range
printf ("x = %d, errno = %d\n", errno);
return 0;
}
输出:
x = 2130706432, errno = 0
x = 2147483647, errno = 34