1

(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?

Community
  • 1
  • 1
Dariusz
  • 21,561
  • 9
  • 74
  • 114

5 Answers5

13

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.

user694733
  • 15,208
  • 2
  • 42
  • 68
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.

jcoder
  • 29,554
  • 19
  • 87
  • 130
  • 1
    @juanchopanza correct, that's why I said if ptr is a user defined type. That does not apply in the users code. I just wanted to make it clear to anyone reading the answer that your can't in general assume that && is short circuited without looking at the types involved. Feel free to improve the wording in the answer if its wrong or confusing. – jcoder Feb 14 '14 at 10:28
  • Ah OK, somehow I managed to read "pointer" in there. I will remove my comment. – juanchopanza Feb 14 '14 at 10:30
  • It doesn't only require you to overload `&&`, but also `!=`, to result in a type with overloaded `&&`. – Christian Rau Feb 14 '14 at 10:30
  • Ok the example here does of course. I just wanted to point out that in general be careful with && though... With a smart pointer don't write " if (sptr && sptr->data())" like you might with a raw pointer. – jcoder Feb 14 '14 at 11:35
1

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.

Sean
  • 60,939
  • 11
  • 97
  • 136
1

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.
Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
  • 3
    True, however this only applies if concurrent access to `ptr` is not protected. Such code I'd consider broken anyway. – alk Feb 14 '14 at 10:33
1

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;
}
barak manos
  • 29,648
  • 10
  • 62
  • 114