问题
(this question is an exact copy of Is compound if checking for null and then other condition in C++ always safe? but about C, not C++. It was pointed out that the question should be more specific).
I have been using the following type of if
condition for a lot of time.
char* ptr = ...;
if (ptr != NULL && ptr[0] != '\0') // <=== is this always safe?
{ /* ... */ }
It relies on ptr != NULL
being checked before ptr[0] !='\0'
.
Is it safe under all standards, compilers, architectures? Or is there a possibility that ptr[0] != '\0'
will be checked before ptr != NULL
?
回答1:
Yes, it is safe.
C standard says (N1570 - 6.5.13 Logical AND operator):
Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; if the second operand is evaluated, there is a sequence point between the evaluations of the first and second operands. If the first operand compares equal to 0, the second operand is not evaluated.
回答2:
If ptr is a built in type then this is always safe. The compiler must evaluate the left hand side first and only evaluate the right hand side if the left side is true.
If ptr is a user defined type (which it isn't here) then this may not apply as operator&& can be overridden in the class and it DOES NOT short circuit like this.
回答3:
Yes its safe. It's called short-circuit evaluation and applies to the logical-and and logical-or operators.
In logical-and (&&) the right side is only evaluated if the left side is true.
In logical-or (||) the right side is only evaluated if the left side is false.
回答4:
The other answers already explain how short circuit evaluation guarantees that the code is safe - however, this only holds for a single thread.
If there are multiple threads executing the same code, and ptr
is not using thread-local-storage, it may well be that in
ptr != NULL && ptr[0] != '\0')
You have a sequence like:
- Thread 1 verifies that
ptr != NULL
is true. - Thread 2 assigns
ptr = NULL
- Thread 1 attempts to access
ptr[0]
and segfaults.
回答5:
In your question, you write char* ptr = ...
.
So the answer depends on the context in which you assign ptr
with a value.
As long as you assign ptr
either with a valid memory address or with NULL
, then it should be safe.
But if you assign ptr
with an invalid memory address which is not NULL
, then your code is unsafe.
For example:
char* ptr = func();
char* func()
{
char* str; // possibly pointing to an invalid memory address which is not NULL
return str;
}
来源:https://stackoverflow.com/questions/21776657/is-compound-if-checking-for-null-and-then-other-condition-in-c-always-safe