Reputation: 131666
I want to adapt a piece of code to be able to run on systems where the null pointer is not 0 in its physical representation. So far in life I've totally ignored the distinction between nullness and 0 - and still today, I don't work on any system which has this distinction in practice - but still.
So, I went and read the C FAQ about nulls again, and particularly 5.19, regarding how to get an "actual zero" pointer. Well, I want to do this in a unit test I'm writing, but - I am worried some of those "tricks" will actually be optimized away by a reasonable compiler.
For example, using memset()
and `memcmp(): Both GCC and Clang see right through that, so that this:
#include <stdio.h>
#include <string.h>
int foo(void* p)
{
void* ref;
memset(&ref, 0, sizeof(ref));
return (memcmp(&p, &ref, sizeof(p)) == 0 ) ? 123: 456000;
}
int bar(void* p)
{
memset(&p, 0, sizeof(p));
return (p == 0) ? 123: 456000;
}
becomes, say:
foo: # @foo
test rdi, rdi
mov ecx, 123
mov eax, 456000
cmove eax, ecx
ret
bar: # @bar
mov eax, 123
ret
So, other than compiling without optimizations, how can I reliably "force a zeroing" of a pointer?
Note: Thanks goes to @Lundin for pointing out that if I use memset()
I also probably want to use memcmp()
).
Upvotes: 2
Views: 169
Reputation: 214060
memset
is the correct solution. And since you compile with compilers that uses zero as null pointer implementation, it might be quite hard to block optimizations from happening.
You have a bug though.
if(p)
checks if that pointer is a null pointer.p == 0
, p == (void*)0
or p == NULL
checks if that pointer is a null pointer.So p == 0
does not check if the internal representation is zero. You'd have to use something like:
void* ref;
memset(&ref, 0, sizeof ref);
if(memcmp(&p, &ref, sizeof p)==0)
Which again probably won't result in anything revolutionary on a system using zero for null pointer representation.
Upvotes: 2