【问题标题】:What is the correct and portable (Clang/GCC) modifier for uint16_t in sscanf?sscanf 中 uint16_t 的正确且可移植的 (Clang/GCC) 修饰符是什么?
【发布时间】:2015-11-12 15:30:56
【问题描述】:

当我尝试编译此代码时收到一条警告消息 sscanf(value, "%h" PRIu16 "B", &packet_size) 使用 Clang 600.0.57 (OS X)。

warning: format specifies type 'unsigned char *' but the argument has type 'uint16_t *'
      (aka 'unsigned short *') [-Wformat]
    if (sscanf(value, "%h" PRIu16 "B", &packet_size) == 1) {
                       ~~~~            ^~~~~~~~~~~~

但是如果我删除修饰符“h”,那么我会在 GCC 4.8.3 (Scientific Linux 7) 中收到以下错误。

warning: format ‘%u’ expects argument of type ‘unsigned int*’, but argument 3 has type ‘uint16_t* {aka short unsigned int*}’ [-Wformat=]
     if (sscanf(value, "%" PRIu16 "B", &packet_size) == 1) {

                                                   ^

什么是 sscanf 中 uint16_t* 的正确且可移植的修饰符?

=== 在下面添加了更多不言自明的示例 ===

test.c

#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS 1
#endif
#include <inttypes.h>
#include <stdio.h>

int main() {
  char* str = "16 bits";
  uint16_t u16;
  sscanf(str, "%h" PRIu16 " bits", &u16); // Clang warning
  sscanf(str, "%" PRIu16 " bits", &u16); // GCC warning
  sscanf(str, "%" SCNu16 " bits", &u16); // OK for both compilers

  printf("%" PRIu16 " bits\n", u16);

  return 0;
}

Clang 警告

$ clang test.c -Wall -Wextra
test.c:10:36: warning: format specifies type 'unsigned char *' but the argument
      has type 'uint16_t *' (aka 'unsigned short *') [-Wformat]
  sscanf(str, "%h" PRIu16 " bits", &u16); // Clang warning
               ~~~~                ^~~~
1 warning generated.

GCC 警告

$ gcc -Wall -Wextra test.c
test.c: In function ‘main’:
test.c:11:3: warning: format ‘%u’ expects argument of type ‘unsigned int *’, but argument 3 has type ‘uint16_t *’ [-Wformat=]
   sscanf(str, "%" PRIu16 " bits", &u16); // GCC warning
   ^

【问题讨论】:

  • SCNsN 代表 scanf()。使用:sscanf(value, "%"SCNu16"B", &amp;packet_size),记得#include &lt;inttypes.h&gt;
  • cplusplus.com/reference/cstdio/scanf 说你想要sscanf(sourcestring,"%hu",&amp;uint16Value)。我不知道PRIu16 正在扩展到什么,但也许它正在扩展到告诉sscanf 寻找unsigned char* 的东西? (或者编译器在发出包含宏的警告时表现不佳?)
  • @RussSchultz cplusplus.com 没有这样的说法。你不能假设typedef unsigned short int uint16_t。将&lt;stdint.h&gt;printfscanf 函数一起使用的可移植方式是使用&lt;inttypes.h&gt; 中提供的常量。

标签: c++ c gcc clang


【解决方案1】:

正如@EOF 在他们的评论中所说,fscanffprintf 都有自己的宏。

final C99 draft 中,§7.8.1 第 4 和 5 条(第 199 页)说&lt;inttypes.h&gt; 应定义以下宏:

  1. 有符号整数的fscanf 宏是:

    SCNdN SCNdLEASTN SCNdFASTN SCNdMAX SCNdPTR
    SCNiN SCNiLEASTN SCNiFASTN SCNiMAX SCNiPTR

  2. 用于无符号整数的fscanf 宏是:

    SCNoN SCNoLEASTN SCNoFASTN SCNoMAX SCNoPTR
    SCNuN SCNuLEASTN SCNuFASTN SCNuMAX SCNuPTR
    SCNxN SCNxLEASTN SCNxFASTN SCNxMAX SCNxPTR

如果您想将uint16_tfscanf 一起读取为十进制数字,则必须使用SCNu16

例子:

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>

int main(void) {
    uint16_t input;

    int items = scanf("fetch %" SCNu16 " bits", &input);

    if (items == 1) {
        printf("I'm busy, go fetch those %" PRIu16 " bits yourself.\n", input);
    } else {
        printf("I don't understand what you're saying.\n")
    }

    return 0;
}

【讨论】:

  • 我建议更新您的答案以显示 如何 使用这些宏。使用模式不明显。
  • @Rhymoid 非常感谢。我在我的问题中添加了一个更好的例子。
猜你喜欢
  • 1970-01-01
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
  • 2012-06-07
  • 2018-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多