如何将十六进制值转换为 WORD、DWORD 或 QWORD 并将结果存储在双精度变量中?
How to cast hex value to WORD, DWORD or QWORD and store the result in a double variable?
我试图通过这种方式将带符号的十六进制数转换为 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;
}
但它 returns 以下内容:
WORD=-3805
DWORD=2147483647
QWORD=2147483647
但为什么 DWORD 和 QWORD 转换没有返回 -3805
?
我的意思是:存储在 DWORD 中的 0xFFFFF123
将包含 -3805
十进制值,而不是 2147483647
预期输出:
WORD=-3805
DWORD=-3805
QWORD=-3805
你有按位的替代方法吗?
0xFFFFF123 超出了 long int 的范围,如果 long int 有 32 位,所以 strtol() return 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;
}
strtol
不假设二进制补码输入。为了让它将某些东西视为负数,您必须使用减号。例如 "-F123"
。这就是为什么第二行和第三行不给出负输出的原因。
对于第一行,您得到预期的输出大多是偶然的。因为 在 调用 strtol
之后,您将十六进制值 0xF123
转换为 int16_t
。它不适合 int16_t
,因此它被转换为负值。
一些错误:
如果 long
不能保存结果,strtol("FFFFFFFFFFFFF123")
将不起作用。你应该使用 strtoll
.
- 要打印 stdint.h 类型,请使用 inttypes.h 中的格式说明符
PRId
,例如:printf("WORD=%" PRId16 "\n", my_int16_t);
- 总的来说,避免有符号数的整数溢出。如果您希望输入适合无符号 32 变量而不是有符号变量,您应该使用
strtoul
等函数,然后转换为有符号类型。
此代码中存在一些错误。
第一行中的主要问题是您不能将 long int 转换为 int16_t
,因为 int16_t
的大小小于 long int
。
此外,您应该使用 PRId16
说明符来打印 int16_t
.
第二行的结果是打印 LONG_MAX
,因为 0xFFFFF123
超出了 long int 的范围。
第三行与第二行有同样的问题,FFFFFFFFFFFFF123
更超出范围,将其转换为 64 位值也无济于事。
此外,您需要使用 %lld
或 PRId64
打印它,正如迈克尔已经说过的那样。
问题是 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
我试图通过这种方式将带符号的十六进制数转换为 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;
}
但它 returns 以下内容:
WORD=-3805
DWORD=2147483647
QWORD=2147483647
但为什么 DWORD 和 QWORD 转换没有返回 -3805
?
我的意思是:存储在 DWORD 中的 0xFFFFF123
将包含 -3805
十进制值,而不是 2147483647
预期输出:
WORD=-3805
DWORD=-3805
QWORD=-3805
你有按位的替代方法吗?
0xFFFFF123 超出了 long int 的范围,如果 long int 有 32 位,所以 strtol() return 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;
}
strtol
不假设二进制补码输入。为了让它将某些东西视为负数,您必须使用减号。例如 "-F123"
。这就是为什么第二行和第三行不给出负输出的原因。
对于第一行,您得到预期的输出大多是偶然的。因为 在 调用 strtol
之后,您将十六进制值 0xF123
转换为 int16_t
。它不适合 int16_t
,因此它被转换为负值。
一些错误:
-
如果
strtol("FFFFFFFFFFFFF123")
将不起作用。你应该使用strtoll
.- 要打印 stdint.h 类型,请使用 inttypes.h 中的格式说明符
PRId
,例如:printf("WORD=%" PRId16 "\n", my_int16_t);
- 总的来说,避免有符号数的整数溢出。如果您希望输入适合无符号 32 变量而不是有符号变量,您应该使用
strtoul
等函数,然后转换为有符号类型。
long
不能保存结果,此代码中存在一些错误。
第一行中的主要问题是您不能将 long int 转换为 int16_t
,因为 int16_t
的大小小于 long int
。
此外,您应该使用 PRId16
说明符来打印 int16_t
.
第二行的结果是打印 LONG_MAX
,因为 0xFFFFF123
超出了 long int 的范围。
第三行与第二行有同样的问题,FFFFFFFFFFFFF123
更超出范围,将其转换为 64 位值也无济于事。
此外,您需要使用 %lld
或 PRId64
打印它,正如迈克尔已经说过的那样。
问题是 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