问题
This was a quiz (not graded) on Coursera. The question was, what does the following code possibly evaluate to? The correct answers were 127 and 0 (other options were crash, -1, 128. Why does the following code possibly evaluate to 0? I understand why it would evaluate to 127. Is it just as simple as the char bytes are uninitialized and therefore random? Can it also possibly evaluate to any # between 0 and 127?
int foo(void) {
char bar[128];
char *baz = &bar[0];
baz[127] = 0;
return strlen(baz);
}
回答1:
Previously this answer had wrong information, this case does not invoke undefined behavior.
Edited answer:
TL;DR We cannot have a definitive answer, the code contains indeterministic behavior.
To elaborate, char bar[128];
is an automatic local variable and if not initialized explicitly, will contain indeterminate values.
Quoting C11
, chapter §6.7.9
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. [....]
In your code, you have assigned value for only one member of the array, at index 127. Remaining elements still have indeterminate value.
Attempt to pass that array (pointer to the first element of the array, basically) to strlen()
, causes a read on those values (in search of a null-terminator) and due to the indeterminate values, there's no guarantee that it will find the null-terminator at any particular location.
- It can very well find a null terminator (ASCII value 0) in the very first element and return 0.
- It can also not find any null terminator (ASCII value 0) in any of the other array elements until the last one and return 127.
- It can find a null terminator anywhere in the array and return that count.
So, there's no definite answer for this question.
Note: (to make up for my wrong understanding to prevent readers from falling into the same trap further)
Here, reading the uninitialized values (i.e., indeterminate values) does not invoke undefined behaviour, as one may think.
The one liner: The address is taken for the object.
There's a detailed discussion on this topic, refer here.
回答2:
The behaviour of the code is indeterminate. By this I mean that the answer could be anything between 0 and 127 inclusive.
strlen
will be reading uninitialised memory up to but not including bar[127]
, which will act as a termination condition.
But because that array consists of char
elements, reading those data is not undefined since char
types cannot have a trap representation. It simply that they contain indeterminate values.
(It would have been an entirely different matter had bar
had static storage duration. Then the answer would always be zero).
The bulk of the comments below are reacting to an incorrect formulation of this answer that stated that the behaviour was undefined.
回答3:
There are two things that could make this code UB, as listed here. This is a variable with automatic storage duration that has its address taken, so the first case definitely does not apply.
The variable is not allowed to hold a trap representation either, as per the definition of trap representations C11 6.2.6.1/5 emphasis mine:
Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined.50) Such a representation is called a trap representation.
This means that the array holds unspecified values. One case of such an unspecified value could be the value 0, at any place in the array, getting treated as a null terminator.
来源:https://stackoverflow.com/questions/41613966/c-char-pointer-length