Why does sscanf not work properly with a bool type

2019-02-17 05:26发布

The output of this code:

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:1

However by changing the int to bool results in strange behaviour:

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

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.

6条回答
ゆ 、 Hurt°
2楼-- · 2019-02-17 05:29

The sscanf function failed because bool is not an int but a 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.

查看更多
smile是对你的礼貌
3楼-- · 2019-02-17 05:35

It could be because sizeof(bool) is sometimes 1 ? So, I don't know much C++, but in C that would be undefined behavior.

查看更多
我命由我不由天
4楼-- · 2019-02-17 05:41

Imagine if bool is only one byte, rather than the four (or even eight) that an int uses. 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. That space would be filled with 0 bytes, effectively terminating your string.

查看更多
淡お忘
5楼-- · 2019-02-17 05:43

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 ?

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;
查看更多
Viruses.
6楼-- · 2019-02-17 05:48

According to the spec for sscanf, the description of %d is:

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.

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.

查看更多
霸刀☆藐视天下
7楼-- · 2019-02-17 05:52

bool is a separate type to int, and is likely to be a single byte (which on most common platforms is smaller than int).

sscanf is not type-safe; 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. 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.

查看更多
登录 后发表回答