Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typecasting NULL pointer in C

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

like image 647
Capricorn Avatar asked Mar 15 '13 10:03

Capricorn


People also ask

Can we typecast null in C?

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.

Can you cast a null pointer?

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.

What is the type of null pointer?

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.

What does pointer null mean in C?

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.


1 Answers

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).

like image 102
Steve Jessop Avatar answered Oct 04 '22 01:10

Steve Jessop