问题
Edit: What about if we had this
char value_arr[8];
// value_arr is set to some value
snprintf(value_arr, 8, "%d", *value_arr);
is this behavior defined?
Let's say for some ungainly reason I have
char value_arr[8];
// value_arr is set to some value
int* value_i = reinterpret_cast<int*>(value_arr);
snprintf(value_arr, 8, "%d", *value_i); // the behaviour in question
Is there a guarantee that, for example, if *value_i
= 7, then value_arr
will take on the value of "7". Is this behavior defined? Such that value_i
is first dereferenced, then passed by value, and then formatted, then stored into the array.
Normally, the value of *value_i
can be expected to not change, but storing the string into value_arr
violates that.
It seems to function as expected when I test it, but I can't seem to find a definitive answer in the documentation. The function signature has ...
, which to my knowledge has something to do with va_list
, but I'm afraid I'm not very knowledgable on the workings of variadic functions.
int sprintf (char* str, const char* format, ... );
回答1:
For the original code, evaluating the expression *value_i
causes undefined behaviour by violating the strict aliasing rule. It is not permitted to alias a char array as int
.
For the edited code, snprintf(value_arr, 8, "%d", *value_arr);
, it is fine and will format the character code of the first character in the array. Evaluation of function arguments is sequenced-before entering the function. (C++17 intro.execution/11)
回答2:
It's undefined behaviour; You use a pointer of type int*
to point to an object of type char[8]
with different / relaxed alignment requirements compared to int*
. Dereferencing this pointer then yields UB.
回答3:
The following can be found at https://en.cppreference.com/w/cpp/io/c/fprintf:
If a call to sprintf or snprintf causes copying to take place between objects that overlap, the behavior is undefined.
I would interpret your example to fall into this case and as such it would be classified as Undefined Behaviour, according to this page.
Edit: Some more details at https://linux.die.net/man/3/snprintf:
Some programs imprudently rely on code such as the following
sprintf(buf, "%s some further text", buf);
to append text to buf. However, the standards explicitly note that the results are undefined if source and destination buffers overlap when calling sprintf(), snprintf(), vsprintf(), and vsnprintf(). Depending on the version of gcc(1) used, and the compiler options employed, calls such as the above will not produce the expected results.
来源:https://stackoverflow.com/questions/53016983/overlapping-memory-with-sprintfsnprintf