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;