3 ms·
> If NULL is a macro not defined as a pointer sized integer, then you're at fault here. If it was you who wrote stdlib.h, sure; otherwise, if you’re on a platf
by mananaysiempre 3y ago
> If NULL is a macro not defined as a pointer sized integer, then you're at fault here.
If it was you who wrote stdlib.h, sure; otherwise, if you’re on a platform where NULL is traditionally defined as 0 and not (void *)0, you’re stuck. A conformant implementation is free to use either definition.
If you want to language-lawyer more heavily, C does not require there to be pointer-sized integers (uintptr_t is optional), does not require that all zero bytes represent a null pointer in memory (unlike for integers), does not require that the implementation choose to store an integer with value zero as all zero bytes (there may be other valid representations), and in any case does not require an implementation to do anything reasonable at all if the caller passes an integer but a vararg callee looks for a pointer (think separate integer and pointer registers).
[I’m not entirely sure if (void *)(void *)0 is a null pointer constant (though it’s certainly an expression that evaluates to a null pointer)—does it count as a zero-valued integer constant expression cast to a pointer to void? So you might not even be able to use (void *)NULL as a hedge against bad platform headers.]
- kazinator 3y agoYou're allowed to do: #undef NULL #define NULL ((void *) 0) Just don't do it prior to the inclusion of any standard header (C or POSIX).
- mananaysiempre 3y agoI don’t think you are? Redefining a reserved identifier is UB per ISO C (any version) 7.1.3p2, and per 7.1.3p1, > Each macro name in [the standard library] is reserved for use as specified if any of its associated headers is included; unless [you’re #undef’ing a function also provided as a macro]. The general idea seems to be that standard headers are allowed to use macros they define, even in other macros they define, and because macro names are late-bound (ugh), even if the user only redefines the name afterwards, every macro that uses it will then be affected. As a silly example, a valid part of stdlib.h could be #define NULL 0 #define EXIT_FAILURE (NULL) #define EXIT_SUCCESS (EXIT_FAILURE+1) and now after your redefinitions EXIT_SUCCESS becomes a constraint violation. (For an implementor to actually do this would of course be dumb, but you did say “allowed”, and that’s what the standard says here.) Or did I misunderstand “use as specified”?
- kazinator 3y agoDo it where it works (hopefully some platform for which you build all the time), and get your enhanced diagnostics there; avoid it where there are problems like this.