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
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.
You can cast null to any source type without preparing any exception. The println method does not throw the null pointer because it first checks whether the object is null or not. If null before it simply prints the string "null". Otherwise, it will call the toString purpose of that object.
A null pointer constant is an integer constant expression that evaluates to zero. For example, a null pointer constant can be 0, 0L , or such an expression that can be cast to type (void *)0 . You can specify any of the following values for a null pointer constant: 0.
A null pointer is a pointer which points nothing. Some uses of the null pointer are: a) To initialize a pointer variable when that pointer variable isn't assigned any valid memory address yet. b) To pass a null pointer to a function argument when we don't want to pass any valid memory address.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With