4

I'm reading c++ code, where the developer often uses this kind of pattern:

float *_array;

//...
while (expression) {

    if (_array) {
        // ...
        _array += 1;
    } else {
        // ...
    }
}

The outer while loop will terminate independently from where _array points to. My question is about the if (_array) condition and the incrementation within that clause.

I first thought that it should check if the pointer "ran out of" the array, but that does not seem to be case. I tested it with this simple snippet:

float *p = new float[5];
int i = 0;
for (i = 0; i < 10; i++) {
    if (p) {
        std::cout << "ok\n";
    } else {
        std::cout << "no\n";
    }
    p += 1;
}

This will print 10 times "ok". So if (pointer) evaluates to true even if the pointer exceeded the defined array length.

But what else could be the purpose of if (pointer) in that context?

basilikum
  • 10,378
  • 5
  • 45
  • 58

6 Answers6

6

Its purpose is to check whether pointer _array is pointing to NULL or not, i.e. to check if it is a NULL pointer.

new throws std::bad_alloc exception and therefore no need to check NULL. In case of malloc, calloc, realloc or new(std::nothrow), if the allocation fails they return NULL. In such case you need to check for NULL.

haccks
  • 104,019
  • 25
  • 176
  • 264
3

In C and C++ a pointer when evaluated in a boolean context returns true if the pointer is not NULL and false if the pointer is NULL.

The form if (ptr) ... is a common shorthand for if (ptr != NULL) ....

This interpretation rule is true even if in the specific platform a NULL pointer is not represented by binary zeros.

6502
  • 112,025
  • 15
  • 165
  • 265
2

The null pointer is implicitly converted into boolean false and the non-null pointers are converted into true.

So you can use either

if(_array != NULL)

or

if(_array)

§ 4.12 Boolean conversions

A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.

betteroutthanin
  • 7,148
  • 8
  • 29
  • 48
1

The code is flawed - the pointer is incremented even if it's NULL.

#include <iostream>
using namespace std;

int main()
{
    float *ptr = nullptr;

    for(int i = 0; i < 5; ++i)
    {
        cout << (ptr ? "ok" : "no") << endl;
        ++ptr;
    }

    cin.get();
}

Output:

no
ok
ok
ok
ok

You'll get access violation if you try to dereference that pointer. Put the pointer incrementation in the if(ptr) clause and it will stay NULL if it was NULL before the loop.

LogicStuff
  • 19,397
  • 6
  • 54
  • 74
  • Thanks for that addition. This snippet was just for me, to see whether or not, a pointer that exceeds the array limit will evaluate to false. I didn't put much more thought in it. – basilikum Apr 26 '15 at 10:34
1

Adding to the main answer: your second code causes undefined behaviour.

Once the loop runs 6 times, p moves past the end of the array and causes undefined behaviour. Pointers may only point to an object, or one past the end, or be null pointers.

This shows why "trial and error" is not a good way to learn about C++ because it is hard to tell the difference between defined behaviour, and undefined behaviour that happens to do what you expect this time.

M.M
  • 138,810
  • 21
  • 208
  • 365
0

As far as I understand, in C, if condition works on whether the value is zero or non-zero. Since NULL pointer has a value of zero, it fails the if condition! In other words, this method can be interpreted as a verification for NULL pointer

Proof

#include <stdio.h>
int main()
{
    int *p = NULL;
    int a = 1;

    printf("%p %d\n", p, p);

    p = &a;
    printf("%p %d\n", p, p);

    return 0;
}

Now when we compile & run this:

$> gcc null.c
$> ./a.out
(nil) 0
0x7fff0556ff3c 89587516

Notice that in the first printf, with the %d, the value of the pointer p is zero. Hence if you use a pointer directly in a if condition, it will act as a true or false, which can be interpreted as NULL pointer or non-NULL pointer.

Best Practice

Also, I would like to add that the usage is from the standard best practices. This is the preferred method for checking if the pointer is NULL as compared to the potentially dangerous & error-prone:

if (p == NULL) {
}

which can be mis-typed (dangerously) into:

if (p = NULL) {
}
meetrp
  • 155
  • 9