By the time I got started on Usenet "All the world's a VAX" was only in use as a proverbial misconception anymore. At the time, all the world was a Sun Workstation.
I also worked on almost all the other engineering workstation platforms, for porting purposes, but a SPARCstation was my preferred main workstation, overall.
(I was a kid who stumbled upon a dream job. So many expensive toys, so much I could learn, and this cool Internet thing...)
You should still cast NULL when passed as an unnamed argument to a variadic function. While NULL is defined to be a null pointer constant, that doesn't mean it has a pointer type (all integer literals with a value of zero are null pointer constants in C, but they have an integer type).
(Strictly speaking, all unnamed pointer arguments to variadic functions should be converted to a compatible pointer type that the variadic function expects. For example, the printf-line of functions expect a pointer-to-void argument for a conversion specifier %p. If you pass a pointer-to-int instead, technically the behaviour is undefined.)
(To whom it may concern: I would appreciate at least a rebuttal. It's not like this is a subjective matter.)
#define NULL 0 #define NULL ((void*)0)
and then passed to a function that expects variadic int* parameters on a machine where register-sized addresses are word-aligned and thus int* has a different sizeof (and/or bit-level representation) than void*.As a practical matter, C implementations typically define NULL as a void pointer, so the cast is not necessary in those implementations (In C++ pre C++11, NULL is always defined as a literal 0, so the cast is definitely necessary).
But it appears the standard allows C implementations to define NULL as a literal 0 or as 0L as well, so the cast is needed in portable code.
But if you cast the intptr to voidptr, the behavior is defined, right? (Besides that %p is nonstandard iirc)
(The reason why I used the word technically earlier was because on all common platforms int-pointers and void-pointers – and indeed all object pointers – have identical binary representation.)
Subject: Ten Commandments For C Programmers
Message-ID: <[email protected]>
Date: Wed, 14-Oct-87 17:35:26 EDT
Subject: The Ten Commandments for C Programmers (Annotated Edition)
Message-ID: <[email protected]>
Date: 4 Nov 90 02:16:18 GMTNot "exotic" so much, really. Obviously those days are long behind us now, but for many years the very last refuge of K&R C was the bootstrap compiler for gcc.
By the 90's, for revenue and product differentiation reasons all the big Unix vendors had moved their optimizing toolchains into their "developer" software packages and out of the base system. But for legacy compatibility reasons they still needed a working K&R C compiler in /bin/cc.
So for almost two decades, the only contact working engineers had with pre-ANSI compilers was using them to bootstrap a real compiler (gcc) on their new, fancy, high performance, very mainstream and non-exotic workstations.
"We recommend that C developers use the C++ compiler to compile C code (using /TP if the file is named something.c). This is the best choice for using Visual C++ to compile C code."
From: https://herbsutter.com/2012/05/03/reader-qa-what-about-vc-an...
In addition to the MSVC issue mentioned in the sibling comment, I've worked on projects that used clang thread safety analysis, which at the time (and maybe still today) was only available for C++, so the build for that analysis was configured to build all C source files as C++.
int *buf = malloc(sizeof(*buf));
(It's noteworthy that while there's an implicit conversion above, there's no such thing as an implicit cast.)Of course it's not something everyone agrees to, but at least a lot of people seem to.
[1] https://stackoverflow.com/questions/605845/do-i-cast-the-res...
What do you think of "auto" in C++ ?
edit: now I see what you mean in the context of adding assertions to make type conversions safer, and how there could be some parallels with auto for that
Whatever the answer, it won't surface a contradiction; but that doesn't mean it's not an interesting, obliquely related question.
The following C code compiles today without complaint on gcc:
foo(i, j) { return i + j; }With linker support, C++ would never have had to resort to name mangling.
The foo(i,j) in your example could have caused the compiler to emit assembly directives to specify the argument types and return type. The assembler could have put these into the object file. The linker could have checked for compatibility when linking. The linker could have produced warnings, errors, or in some cases even thunks.
> As a lamentable side issue, there has been some unrest from the fanatics of the Pronoun Gestapo over the use of the word ``man'' in this Commandment, for they believe that great efforts and loud shouting devoted to the ritual purification of the language will somehow redound to the benefit of the downtrodden (whose real and grievous woes tendeth to get lost amidst all that thunder and fury). When preaching the gospel to the narrow of mind and short of temper, the word ``creature'' may be substituted as a suitable pseudoBiblical term free of the taint of Political Incorrectness.
Most of the advice is still good, but I would object to (3):
* Excessive casting can be a problem in itself, as it hides genuine type errors (e.g. you think you're casting an int to long, but in reality the variable is a pointer)
* Casting NULL is pointless, as it's already defined by the standard to be a pointer constant, compatible with all data pointers.
* Much of the language about "prototypes" (a.k.a. standard C) was justified at the time, but no longer reflects reality nowadays. It would have to be a very exotic platform that still uses a pre-ANSI C compiler.