有没有办法使用scanf将unsigned char十进制输入读入uint8_t变量?
我担心如果我将%hu或%u读入uint8_t,它可能会破坏相邻的内存,因为uint8_t是一个字节,但%hu是2个字节,%u是4个字节。
我正在使用MinGW32
gcc.exe (GCC) 4.9.3
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
我担心的代码:
/* worried.c - issue demo code. */
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(int argc, char **argv)
{
uint8_t filler1 = 17; /* do not corrupt me please. */
uint8_t my_mem;
uint8_t filler2 = 39; /* do not corrupt me please. */
printf("please enter a number: $ ");
scanf("%u", &my_mem); /* corrupts fillers... */
// scanf("%hu", &my_mem); /* this also corrupts... */
// scanf("%hhu", &my_mem); /* still corrupts... */
// scanf("%"SCNu8, &my_mem); /* still corrupts... */
// scanf("%"PRIu8 "\n", &my_mem); /* still corrupts... */
printf("filler1 = %u.\n", filler1);
printf("my_mem = %u.\n", my_mem);
printf("filler2 = %u.\n", filler2);
return 0;
}
请注意,上面的代码确实破坏了填充程序,这在读取稍后将直接写入二进制(记录)文件的结构时是灾难性的。
我可以通过从一个临时变量中进行转换来解决它,但这对我的程序需要一些额外的工作,我想知道我是否可以避免强制我的程序,并直接读入my_mem。
到目前为止,似乎最有可能的解决方案是:
可移植的唯一方法适用于GCC4.9.3和更新版本 通过铸造。在GCC5.2上有更优雅的解决方案,例如%HHU, 但他们在GCC4.9.3上行为不端。
答案 0 :(得分:1)
我还不能评论,所以我会留下答案。按照其他人的建议使用scanf("%hhu", &my_mem);
会删除编译错误:
test.c: In function ‘main’:
test.c:12:11: warning: format ‘%u’ expects argument of type ‘unsigned int *’, but argument 2 has type ‘uint8_t * {aka unsigned char *}’ [-Wformat=]
scanf("%u", &my_mem); /* corrupts fillers... */
^
并生成正确的输出。
please enter a number: $ 45
filler1 = 17.
my_mem = 45.
filler2 = 39
使用gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010
进行测试。
答案 1 :(得分:1)
使用兼容的编译器,使用SCNu8
@BLUEPIXY
#include <stdint.h>
#include <inttypes.h>
if (1 == scanf("%" SCNu8, &my_mem)) Oh_happy_day();
使用较少的编译器,获取新的编译器或使用所有准备好的OP。
unsigned u;
if (1 == scanf("%u", u)) {
my_mem = u;
Oh_somewhat_happy_day();
}
或者自己定义SCNu8
(它是一个宏)
#include <stdint.h>
#include <inttypes.h>
#ifndef SCNu8
#define SCNu8 "hhu"
#endif
if (1 == scanf("%" SCNu8, &my_mem)) Oh_happy_day_again();
答案 2 :(得分:1)
您遇到了编译错误。在Windows中使用MinGW会出现此错误,因为scanf
调用的默认操作模式是将调用转发到Microsoft C运行时,该运行时不支持%hhu
。
有一个可以与MinGW一起使用的开关,可以使用自己的scanf
实现和其他此类功能,而不是转发给Microsoft。如果使用以下开关进行编译:
-std=c11 -D__USE_MINGW_ANSI_STDIO
然后它可以解决问题。使用此编译器,默认情况下不符合标准,您必须提供各种开关才能使其在标准模式下运行。
我用MinGW-w64 - 已解散的MinGW项目的现代分支 - 和gcc 4.9.2测试了这个,它对我有用。 YMMV