Older C compilers will let you get away with a lot of sins which a modern C compiler will (correctly) call you out for.
Older C compilers will let you get away with a lot of sins which a modern C compiler will (correctly) call you out for.
Under some very old C standards, maybe. But C99 requires that you at least declare a function before calling it.
There is no such requirement of a declaration before first call in Java for example?
Kind of like how the JavaScript dudes all use this ".ts" stuff now for convenience that processes into ".js"
let x: number = 6;
You should instead allow the compiler to infer where it can and do
let x = 6;
Inference doesn't work across function calls like it does (did?) in Flow, which is a good thing, so those always need to be typed.
If you wanted the type of x to be 6 instead of number, you would use
let x = 6 as const;
extern int id();
The empty parentheses meant it could take any number of arguments, since it was declared in the traditional style, where the argument types weren't specified first.This implicit declaration meant that if it was later defined in the same file as returning a type other than int, the compiler wasn't permitted to go back up in the file and treat the function call as though it returned a type other than int.
This requirement was removed in C99, but in practice, compilers kept doing it for backwards compatibility, even when not invoked in C90 mode.
You do have analyses like ctags. In theory the compiler could use ctags to find definitions in source code. My experience is ctags can get confused. It's possible in a set of files to have multiple implementations of a function and ctags can't tell which one is used. And I see cases where it can't find definitions.
Personally I'd be happy if the compiler tried to find a missing definition using ctags and issued a warning.
I have wondered if adding funct, public, private keywords to the language might allow the compiler to reliably find function and stuct definitions in source files.
That's not necessarily true. It's possible that the symbol is a function pointer; calling a function pointer requires slightly different code generation. Compare the generated code between:
void fn(void);
void call_fn(void) { fn(); }
and void (*fn_ptr)(void);
void call_fn_ptr(void) { fn_ptr(); }
In practice, it's probably a function, and that's what the compiler assumes if there's no declaration to go off of. But we all know what happens when you make assumptions.you mean the linker will throw an error. The linker is trying to link together the "references" be they forward or backward, that the compiler has created, and the compiler needs to have generated the right references, round peg round hole, square peg square hole.
You don't want your linker throwing errors, it doesn't have the context the compiler does; and you don't want to turn the linker into ChatGPT that can converse with you about your source code, just use the C version of forward references which are not particularly forward, they just say "I don't know where this is defined, it's just not defined here, but we know it's a square peg"
For example, there are architectures where space is tight (embedded for example) and nearby things can be called more efficiently than far away things, so the compiler needs to generate as many near calls as it can, falling back to far away when it has to. It doesn't know in advance how far away things are going to be, but it might uncover plenty of near things as it goes. Square pegs, round pegs.
when you recompile your project code, the library code, is not necessarily around. When other people recompile their library code, your project code isn't around. What's the size of what's being put on the stack? Still gotta get the square/round pegs right.
Win32 C code from way back.
Heh.
Where is that written? Please quote the standard. My reading of ISO/IEC 9899:TC3 is that Foreword says (paraphrasing) "hey, we removed implicit int and implicit prototypes from the standard". So they simply stopped specifying it, but as far as I can tell, the standard says nothing about forbidding them. From my point of view, that means compilers are free to still implement implicit types as a compiler extension to the language, and everyone does, because that extension is needed in order to support the older c89 standard. It would only impact people who want to be able to claim their codebase is c99 standard compliant, because you can't do that if you depend on compiler extensions.
ISO/IEC 9899:TC3 [1] §6.5.1 ¶2: "An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator)."
There's even a footnote to underscore this point: "79) Thus, an undeclared identifier is a violation of the syntax."
[1]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
https://en.m.wikipedia.org/wiki/Forward_declaration
https://en.m.wikipedia.org/wiki/Pascal_(programming_language...
https://en.m.wikipedia.org/wiki/Object_Pascal
https://www.thedelphigeek.com/2017/03/forward-record-declara...
if(*(Ptr = argv[i]) == '-') {
Older C compilers did let you get away with more, like using integers as pointers, and dereferencing pointers as though they were struct pointers when they aren't. But I don't see that in this code.It's not even a good idea to do that on modern computers, because implicitly declared functions do type promotions from float to double and char/short to int, and on the System V ABI, it has to pass in the number of floating point arguments there are in register eax.
A low bar, really :-P
In older C compilers (maybe pre-ANSI, or later, can't remember), you could literally write i[a] instead of a[i], where a was an array and i was an int, and it would work equivalently, i.e. no compiler error, and give the same result as a[i]. This was because a was the address of the start of the array, and i was an offset, so a[i] actually meant *(a + i), which, by the commutative property of arithmetic, was equivalent to *(i + a), which was equivalent to i[a].
I had read this in some C book, maybe K&R or the Waite Group C Microsoft Bible.
Never forgot it, because it was counter-intuitive, unless you knew the above reason.
And tried it out in one or more C compilers at that approximate period, and it worked as stated.
https://godbolt.org/z/37Kv44o1b
> I had read this in some C book, maybe K&R or the Waite Group C Microsoft Bible.
I haven't read the Microsoft C Bible, but it does say this in K&R while explaining pointers.
Wow, good to know.
>but it does say this in K&R
Then that must be where I had read it.