【问题标题】:Why does sscanf not work properly with a bool type为什么 sscanf 不能与 bool 类型一起正常工作
【发布时间】:2011-10-05 07:53:42
【问题描述】:

这段代码的输出:

const char *buff = "*_2D 1";
char field[10];
int flag;
sscanf(buff, "%s %d", field, &flag);
printf("field:%s flag:%i\n", field, flag);

field:*_2D flag:1

但是,将 int 更改为 bool 会导致奇怪的行为:

const char *buff = "*_2D 1";
char field[10];
bool flag;
sscanf(buff, "%s %d", field, &flag);
printf("field:%s flag:%i\n", field, flag);

输出为field: flag:1

谁能解释这里发生了什么?我原以为 bool 会被解释为一个 int,它似乎是,但字符串的其余部分消失了。

【问题讨论】:

  • 将 C++ 类型与 C IO 函数混合是一个的想法。
  • @ybungalobill: 什么 C++ 类型?
  • @Salgar:它也是 C99 类型(别名)。但是你已经用“C”和“C++”标记了这个问题;您实际使用的是哪种语言?
  • @Salgar:旧 C 还是 C99?如果你包含 stdbool.h,C99 就有它

标签: c++ c boolean scanf


【解决方案1】:

可能是因为 sizeof(bool) 有时是 1 ?所以,我不太了解 C++,但在 C 中这将是未定义的行为。

【讨论】:

    【解决方案2】:

    想象一下,如果bool 只有一个字节,而不是int 使用的四个(甚至八个)字节。然后告诉sscanf &flag 是一个指向int 的指针,最终会覆盖堆栈上其他地方的三个或七个字节——这可能就在你的field 变量的顶部。该空间将被 0 个字节填充,有效地终止您的字符串。

    【讨论】:

    • 你是对的,我没有意识到我平台上的sizeof(bool)是1。谢谢:)
    【解决方案3】:

    boolint 的独立类型,并且可能是单个字节(在大多数常见平台上小于 int)。

    sscanf 不是类型安全的;您是在告诉它(使用%d 转换说明符)您正在提供指向int 的指针,因此它假定在那里写int 是安全的。如果实际类型更小,那么您将获得未定义的行为;最有可能的是,其他局部变量将被覆盖,或者堆栈帧将被破坏。在这种情况下,它看起来像是用整数值1 的零值字节覆盖了field 的开头。

    【讨论】:

      【解决方案4】:

      根据spec for sscanf,%d的描述是:

      匹配一个可选带符号的十进制整数...在没有大小修饰符的情况下,应用程序应确保相应的参数是指向 int 的指针。

      也来自相同的规范,

      如果转换的结果不能在提供的空间中表示,则行为未定义。

      由于 sizeof(bool)

      【讨论】:

        【解决方案5】:

        sscanf 函数失败,因为 bool 不是 int 而是 char

        试试这个:

        const char *buff = "*_2D 1";
        char field[10];
        char flag;
        sscanf(buff, "%s %d", field, &flag);
        printf("field:%s flag:%i\n", field, flag);
        

        它会给你同样的错误。

        【讨论】:

        • bool 也不是char;它是一个独特的类型(假设它是 C++ 或带有 <stdbool.h> 的 C99),并且不保证与 char 的大小相同。
        • ...被认为是 sscanf 的“一个字节的有符号数”(如 char)(在 stdbool.h 中,_Bool 只是一个 typedef)
        • @Asgar: no: 在 C99 中,bool 是一个扩展为 _Bool 的宏; _Bool 是一种内置类型,与 char 不同。在 C++ 中,bool 是一种内置类型,同样不同于 charsscanf(和它所引用的fscanf)的规范根本没有提到bool(或_Bool)。
        【解决方案6】:

        如果您使用的是 C++(从您的 cmets 看来就是这种情况),为什么不使用 C++ 流而不是 C 风格的 scanf 方法?

        const std::string buff = "*_2D 1";
        std::string field;
        bool flag = false;
        std::istringstream ss(buff);
        ss >> field >> flag;
        std::cout << "field:" << field << " flag:" << flag << std::endl;
        

        【讨论】:

        • 确实,很遗憾我最初并没有写这个。这就是软件。
        • @Salgar : 我太了解了 :)
        猜你喜欢
        • 2021-08-18
        • 2021-12-06
        • 2020-09-01
        • 2021-12-15
        • 1970-01-01
        • 1970-01-01
        • 2023-03-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多