Raymend Chen has probably forgotten more about programming than I'll ever know, but aren't the first two blah() function examples either missing a } or have a superfluous { after the else?
show comments
CodeArtisan
Until C23, you could declare a pointer to a procedure that takes an unspecified amount of any type arguments like this
If you compile with -std=c23, both gcc and clang will throw an error ( (*f)() is now the same as (*f)(void) )
show comments
anitil
I had never considered the idea of passing too few register params so I didn't immediately think of the reuse problem. And I had no idea about Itanium's Not-a-thing bit! Always a good read from Raymond Chen.
charleslmunger
I had fun exploiting this to detect the falling convention used by some code at runtime - there were two different options depending on OS version; one passed a jnienv* as the first param, the other did not. So if I called it with 0, I could tell which was being used based on whether the first argument was NULL or not. Only used for specific architectures with a defined ABI that behaved this way, of course.
_kst_
It's not even possible to pass too few arguments to a function in C unless you go out of your way to write bad code.
You can write a function declaration that's inconsistent with its definition in another translation unit. Declaring the function in a shared header file avoids this.
You can use an old-style declaration that doesn't specify what parameters a function expects. Don't do that. Use prototypes.
You can use a cast to convert a function pointer to an incompatible type, and call through the resulting pointer. Don't do that.
You can call a function with no visible declaration if your compiler overly permissive or is operating in pre-C99 mode. Don't do that.
show comments
hyperhello
Do you really not ‘pass’ register parameters? How can anyone tell if you didn’t?
show comments
LelouBil
Interesting that some CPUs have a calling convention "built-in"
9fwfj9r
I regard this yet another unintuitive Itanium quirk that makes it failed.
rurban
Of which decade is this post? I cannot think of any modern architecture which still passes args on the stack.
Raymend Chen has probably forgotten more about programming than I'll ever know, but aren't the first two blah() function examples either missing a } or have a superfluous { after the else?
Until C23, you could declare a pointer to a procedure that takes an unspecified amount of any type arguments like this
https://godbolt.org/z/s6e5rnqv9If you compile with -std=c23, both gcc and clang will throw an error ( (*f)() is now the same as (*f)(void) )
I had never considered the idea of passing too few register params so I didn't immediately think of the reuse problem. And I had no idea about Itanium's Not-a-thing bit! Always a good read from Raymond Chen.
I had fun exploiting this to detect the falling convention used by some code at runtime - there were two different options depending on OS version; one passed a jnienv* as the first param, the other did not. So if I called it with 0, I could tell which was being used based on whether the first argument was NULL or not. Only used for specific architectures with a defined ABI that behaved this way, of course.
It's not even possible to pass too few arguments to a function in C unless you go out of your way to write bad code.
You can write a function declaration that's inconsistent with its definition in another translation unit. Declaring the function in a shared header file avoids this.
You can use an old-style declaration that doesn't specify what parameters a function expects. Don't do that. Use prototypes.
You can use a cast to convert a function pointer to an incompatible type, and call through the resulting pointer. Don't do that.
You can call a function with no visible declaration if your compiler overly permissive or is operating in pre-C99 mode. Don't do that.
Do you really not ‘pass’ register parameters? How can anyone tell if you didn’t?
Interesting that some CPUs have a calling convention "built-in"
I regard this yet another unintuitive Itanium quirk that makes it failed.
Of which decade is this post? I cannot think of any modern architecture which still passes args on the stack.
Itanium? Stone age