I have a structure
struct detail {
int id;
uintptr_t init;
// blah blah
};
struct detail info;
info.id = 1;
info.init = (uintptr_t)NULL;
I have to make the the init
member NULL. What may/may not happen if I typecast(or do not typecast) NULL
? What if I directly assign it NULL like info.init = NULL;
Does it make any difference with respect to runtime errors. It compiles fine. But the execution of the code is my main concern.
Thanks
There is no guarantee in the standard that if ptr
is a null pointer, then (uintptr_t)ptr
is 0
.
If you don't care about systems on which null pointers and zero integers aren't equivalent, then info.init = 0;
is fine.
The init
member has integer type, it cannot be "made null". You can assign 0
to it, or you can assign to it the result of converting a null pointer to uintptr_t
. On almost every C implementation ever, those are the same thing. But it is not guaranteed, and there have been systems on which it is not the same.
NULL
might be a null pointer, or it might be an integer constant 0
. In the latter case, there is a guarantee in the standard that (uintptr_t)(NULL)
is 0
. So there can be implementations on which info.init = NULL; (void*)(info.init);
has undefined behavior. It wouldn't result in a null pointer if the integer equivalent of null isn't 0, and computing an invalid pointer value is UB.
So, if you want to guarantee that info
, when converted to a pointer type, results in a null pointer then for true portability you should do info.init = (uintptr_t)(void*)(NULL);
. You could optionally give the reader an extra clue by including the pointer type that the uintptr_t
is going to be converted to, instead of void*
. There are very few good reasons for storing a uintptr_t
, so hints what is going on might help the reader.
Note that there is a guarantee in the standard that a zero-valued constant expression, converted to pointer type, is a null pointer. This does not imply that a zero-valued non-constant expression, converted to a pointer type, is a null pointer. Neither does it imply that a null pointer, converted to integer type, is 0. Those last two things happen to be true in most implementations (including all "modern" ones).
NULL is a built in constant with a value matching whatever a null pointer is on your system. It's perfectly valid to assign the constant value to an int the same size (or bigger) than a pointer on your system.
I would vote for the cast here, since assigning pointers to integers is generally not allowed and will generate a warning. It's a very good idea to use intptr_t
of course, since it's big enough.