3 ms·
0 never should have been overloaded in C to refer to the NULL pointer. With pointer assignment and comparison it transforms to the platform's encoding for NULL
by kevin_thibedeau 3y ago
0 never should have been overloaded in C to refer to the NULL pointer. With pointer assignment and comparison it transforms to the platform's encoding for NULL which isn't necessarily all zeros. No other literal has this sort of magic.
- WalterBright 3y agoThis works in Standard C: int *p = 3;
- kevin_thibedeau 3y agoThe address is still 3 which has valid applications. C is permissive enough to run on platforms that don't use address 0 for NULL. With pointer operations the compiler will change the encoding from 0 to that platform's NULL address. int *p = 0; intptr_t i = (intptr_t)p; if(i == 0) ... // Isn't always true
- LegionMammal978 3y agoThat's a compiler extension. In C17, 6.5.16.1 (Simple assignment) implies that the RHS of an assignment to a pointer must either have pointer type or be a null pointer constant (i.e., an integer constant equal to 0, or such a constant casted to pointer type), and 6.7.9 (Initialization) states that "the same type constraints and conversions as for simple assignment apply" to expressions used as initializers.
- Kamq 3y ago"standard" C implies default to me, so the post is probably referring to C89 or C99, which are significantly more used than C17.
- LegionMammal978 3y agoThis particular rule is essentially unchanged from C89 (3.5.7 for initialization, 3.3.16.1 for simple assignment) and from C99 (6.7.8 for initialization, 6.5.16.1 for simple assignment). Generally, most existing rules don't change much at all across the C Standard versions.
- ynik 3y ago"Standard C" is the C that was standardized. This is not what you get from your compiler by default! With gcc, you have to use `gcc -std=c99 -pedantic-errors`, otherwise it will accept programs which are invalid according to the standard.
- Gibbon1 3y agoI like to point out that AVR micro's reading and writing to address 0 is legit. On the ARM Cortex I think address 0 is the initial stack pointer value. My opinion is NULL being something special in the language is mathy CS academics trying to turn C into a mathy abstract language. Which it ain't.
- jcelerier 3y agoC is officially a mathy abstract language since 1989, the compilers just took some time to catch up. > 2.1.2.3 Program execution > The semantic descriptions in this Standard describe the behavior of an abstract machine [...]
- Gibbon1 3y agoThe mathy version is C is useless for real programs.
- kazinator 3y agoThe C language existed before there was a preprocessor which made it possible to define NULL.
- kevin_thibedeau 3y agoThis has nothing to do with the preprocessor. The concept of NULL existed before the macro was standardized. Literal zeros were the way to refer to it which was a design mistake.
- kazinator 3y agoI think it's a fine design. Obviously, the C++ people who invented virtual void fun() = 0; were blind to whatever mistake it embodies. When I gained the proper understanding that 0 is a null pointer constant, I immediatelly stopped using NULL. It's so much nicer. - It works fine in a typeless language in which every value is a machine word, and integers and the null pointer share exactly the same representation. - It works fine in a strongly typed language, where context indicates what zero means, even in the context of different types of different sizes and representations. Unfortunately C (and also C++) contains some untyped areas, like variadic argument lists. I would have designed it differently: only the token 0 would have the special overloaded meaning, and not all constant zero-valued expressions of any integer type. So (0 + 0) would not be a null pointer. In unsafe contexts, the use of a 0 token would be diagnosed. printf("...", ... 0, ...); // diagnosed printf("...", ... 0L, ...); // not diagnosed: argument of long type printf("...", ... 0 + 0, ...); // not diagnosed: argument of int type printf("...", ... (void *) 0, ...); // not diagnosed: null pointer of (void *) type. I think I would also not have the hexadecimal or octal zero tokens be the null pointer constant: char *p = 0; // null pointer, no diagnostic char *q = 0x0; // error, integer to pointer with no cast The downside is that the AST would have to retain that representation detail somewhere (possibly just in a single Boolean flag).
- kevin_thibedeau 3y agoThis isn't just a C++-ism. The null pointer constants are only more prominent in C++ because of the rejection of void * even though it isn't any "safer" to have a special integer literal with the same semantics. Ultimately, it all comes from K&R C. There are legitimate cases where you need a function pointer assigned to address zero (reset vectors commonly). The correct behavior in C is ambiguous if the null address isn't also 0 since the standard doesn't call out special behavior for function pointers. That wouldn't be the case if nullptr had been standardized earlier and there was no need for the magic 0 as a null pointer constant.