简体   繁体   中英

Why does sscanf not work properly with a bool type

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.

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.

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 .

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

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.

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.

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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