简体   繁体   English

为什么 sscanf 不能与 bool 类型一起正常工作

[英]Why does sscanf not work properly with a bool type

The output of this code:这段代码的output:

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

is field:*_2D flag:1field:*_2D flag:1

However by changing the int to bool results in strange behaviour:然而,通过将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);

The output is field: flag:1 output 是field: flag:1

Can anyone explain what is happening here?谁能解释这里发生了什么? I would've thought the bool would be interpreted as an int, which it appears to be, but the rest of the string disappears.我原以为 bool 会被解释为一个 int,它似乎是,但字符串的 rest 消失了。

Imagine if bool is only one byte, rather than the four (or even eight) that an int uses.想象一下,如果bool只有一个字节,而不是int使用的四个(甚至八个)字节。 Then telling sscanf that &flag is a pointer to an int will end up overwriting either three or seven bytes elsewhere on the stack -- which could be right on top of your field variable.然后告诉sscanf &flag是一个指向int的指针,最终会覆盖堆栈上其他地方的三个或七个字节——这可能就在你的field变量的顶部。 That space would be filled with 0 bytes, effectively terminating your string.该空间将填充 0 个字节,有效地终止您的字符串。

bool is a separate type to int , and is likely to be a single byte (which on most common platforms is smaller than int ). bool是与int不同的类型,并且可能是单个字节(在大多数常见平台上小于int )。

sscanf is not type-safe; sscanf不是类型安全的; you are telling it (with the %d conversion specifier) that you are providing a pointer to an int , and so it assumes that it is safe to write an int there.您正在告诉它(使用%d转换说明符)您正在提供一个指向int的指针,因此它假定在那里写一个int是安全的。 If the actual type is smaller, then you'll get undefined behaviour;如果实际类型更小,那么您将获得未定义的行为; most likely, either other local variables will be overwritten, or the stack frame will be corrupted.最有可能的是,其他局部变量将被覆盖,或者堆栈帧将被破坏。 In this case, it looks like it is overwriting the beginning of field with the zero-valued bytes of the integer value 1 .在这种情况下,看起来它正在用 integer 值1的零值字节覆盖field的开头。

It could be because sizeof(bool) is sometimes 1 ?可能是因为sizeof(bool)有时是1 So, I don't know much C++, but in C that would be undefined behavior.所以,我不太了解 C++,但在 C 中,这将是未定义的行为。

According to the spec for sscanf , the description of %d is:根据sscanf 的规范, %d 的描述是:

Matches an optionally signed decimal integer... In the absence of a size modifier, the application shall ensure that the corresponding argument is a pointer to int.匹配可选带符号的十进制 integer... 在没有大小修饰符的情况下,应用程序应确保相应的参数是指向 int 的指针。

Also from the same spec,同样来自相同的规格,

if the result of the conversion cannot be represented in the space provided, the behavior is undefined.如果转换的结果不能在提供的空间中表示,则行为未定义。

Since sizeof(bool) < sizeof(int), you are in the dreaded Undefined Behavior zone, and anything can happen.由于 sizeof(bool) < sizeof(int),你处于可怕的未定义行为区域,任何事情都可能发生。

The sscanf function failed because bool is not an int but a char sscanf function 失败,因为bool不是int而是char

Try this one:试试这个:

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

It'll give you the same error.它会给你同样的错误。

If you are using C++ (which appears to be the case from your comments), why not use C++ streams instead of the C-style scanf approach?如果您使用的是 C++ (从您的评论看来就是这种情况),为什么不使用 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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM