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
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.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.
There is no guarantee in the standard that if
ptr
is a null pointer, then(uintptr_t)ptr
is0
.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 assign0
to it, or you can assign to it the result of converting a null pointer touintptr_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 constant0
. In the latter case, there is a guarantee in the standard that(uintptr_t)(NULL)
is0
. So there can be implementations on whichinfo.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 doinfo.init = (uintptr_t)(void*)(NULL);
. You could optionally give the reader an extra clue by including the pointer type that theuintptr_t
is going to be converted to, instead ofvoid*
. There are very few good reasons for storing auintptr_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).