C++ null pointers

Started by
23 comments, last by ToohrVyk 17 years, 6 months ago
Quote:Original post by Spoonbender
Quote:
I would have, but my dead-tree-paste version is at home right now, so I don't have access to it, and it isn't legally available online as far as I know.

Isn't it? I found it available online in pdf format a while back. Was that illegal?
*feels guilty*


The actual standard isn't legally available for free, most (all?) of the drafts for the standards are available though, and they are pretty close to the actual standard.
Advertisement
Quote:Original post by Anonymous Poster
NULL is either defined as (void*)0 or 0, so it IS null.


Not in C. (int)1.5f isn't 1.5f, and (void*)0 isn't 0. The C standard ensures that the 0 literal, when evaluated in a pointer context, is transformed into a NULL pointer. In C, the NULL pointer may or may not be represented as an integer-sized block of memory filled with zero bits. When evaluated in a boolean context (such as an if) clause, any pointers but the NULL pointer evaluate to true, while the NULL pointer evaluates to false.

Note that C does not guarantee that:

  • Setting all the bits of a pointer to zero creates a NULL pointer (as a matter of fact, several machines have a non-zero NULL pointer).
  • Setting a pointer to a zero-valued variable (as in int x = 0; void* y = x;) creates a NULL pointer.


In short, the only safe way to create a NULL pointer in C is through the compile-time conversion of the 0 literal into a pointer. Merely setting the pointer to zero is not enough.
Quote:
There may be something in the C++ standard which implicitely states that the representation is guarenteed to be 0,

It states that the value representation of pointers is implementation defined.

However, it is guaranteed that a constant expression that evaluates to zero (during assignment, initialization or comparison of a pointer) is converted to value (the null pointer) and that this value is guaranteed to be distinguishable from a pointer to anything else. This doesn't mean that that null pointer has the same bit pattern as zero, however.

So, in your case, memset() is not a safe way set the pointers to null, because it will simply copy the bitpattern of zero into them. Then need to explitly be assigned or initialized to zero. There's no other way.

EDIT: Eh, I was slow.
Thank you, CTar and jpetrie, for the clarifications. So, it does seem that C++ follows in the tracks of C on this point too.
The truth is it doesn't matter what the C++ spec says, it all depends on what you actually need. Not to sound pessimistic but the truth is that to develop for all architectures is essentially impossible, since the various querks even in the compilers would make program maintenence a nightmare and not engineeringly 'sane'.

What I think you should do is decide whether to natively support architectures that use non 0 null pointers or whether to search for all usages of pointers at a later date to fix any issues caused by ignoring them.

If you decide to support them then just add a null definition to your project, this will work on almost all architectures (some operator overloading may be needed on more exotic machines for the operator == to work but that's ok). Otherwise use an is_null predicate for the best compatibility.

Of course if you only need to deal with 'real' systems that tend to maintain compatibility with more usual architectures then assuming 0 (and therefore also NULL) will suffice.

ps. on a side note you might want to see if the spec indicates whether pointer 'truth' value is always guarantee'd to be correct, but I believe it doesn't (unfortunately I don't have a copy of the spec).

Good Luck

Lorenz

edit: lol, i guess someone already got the answer in here anyway.
Quote:Original post by ToohrVyk
In C, the following code is not guaranteed to set the pointers a and b to NULL:

typedef struct { int *a, *b; } S;

int main() {
S s;
memset(&s,0,sizeof S);
}

Does this problem also exist in C++, or is the C++ standard also unspecific about NULL pointer representation?


Going back to the example then, the safe method(if the real version was as simple as this) would be:
Quote:
struct S
{
S():a(NULL),b(NULL){}
int* a,*b;
};

Oops
Quote:rvalue of integer type that evaluates to zero.

a(0),b(0) is valid
CTar, going to my std headers it has this written:
#define NULL (void*)0
So its not my fault it isnt actually "standard".
Quote:Original post by Anonymous Poster
CTar, going to my std headers it has this written:
#define NULL (void*)0
So its not my fault it isnt actually "standard".

But it is your fault you're using a broken compiler. You should consider updating. Even if the standard didn't explicitly outlaw that definition, it would still be invalid: implicit conversion from void* to other pointer types is not allowed.
Quote:
The truth is it doesn't matter what the C++ spec says, it all depends on what you actually need. Not to sound pessimistic but the truth is that to develop for all architectures is essentially impossible, since the various querks even in the compilers would make program maintenence a nightmare and not engineeringly 'sane'.

While true, you can go a long way by avoiding things that are obviously unsafe in favor of nice, well defined constructs. Using default constructors instead of memset isn't exactly bending over backwards for compatability purposes.

CM
Really, is this something you need to worry about?
Are you writing software for all CPUs or some special machine?

This is a laugheable
http://c-faq.com/null/machexamp.html

They must be ancient machines from the 80's

Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

This topic is closed to new replies.

Advertisement