If you're curious about my remark that the function typedef is useless, it's because you can't use it for definitions, just for declarations. You can do this:
typedef int functype(char* x);
functype myfunc;
...and it's essentially equivalent to:
int myfunc(char* x);
...but then you still need to define myfunc() "manually" by restating the parameters and the return value. This won't work:
"Three expressions are still required by the compiler, but in C, there is an implicit semicolon after a function definition (void _() { })."
No, there's no implicit semicolon. The syntax for a for statement (as of C23) is:
for ( expression[opt] ; expression[opt] ; expression[opt] ) secondary-block
for ( declaration expression[opt] ; expression[opt] ) secondary-block
The second form allows a declaration (typically something like "int i = 0;" in place of the first expression. But there's no semicolon after the "declaration" term in the second form -- because most declarations provide their own semicolons. For example, "int i" is not syntactically a declaration, but "int i;" is.
gcc appears to be treating a function *definition* as a *declaration*. As far as I can tell, that's incorrect (though of course gcc can do anything it likes as an extension).
There was a change in this area between C17 and C23. C17 has a constraint: "The declaration part of a for statement shall only declare identifiers for objects having storage class auto or register." C23 dropped that constraint.
And even if we assume that a function definition is a declaration, the program still violates a constraint. If you compile with "-std=c23 -pedantic-errors", gcc complains "error: ISO C forbids nested functions".
Ah, yeah. I saw that part of the spec after discussing this example on Mastodon beforehand. But I explained it a lot worse than you did. By "implicit semicolon", I meant that a function definition doesn't require an explicit semicolon at the end. But that's a boneheaded and inaccurate way to express it.
Thanks for a proper analysis. I edited the text to better capture the gist of this, I think.
Have you looked at Duff's Device? It weaves a do/while loop into a switch statement. It's the earliest example of C language abuse I learned about (and it wasn't theoretical, Duff actually used it as an optimization).
Totally degen, loved it :) How come you are so familiar with all those arcane obscure specifications of the C standard? Had you been a business lawyer, you would be filthy rich right now, combining arcane loop-holes ad absurdum to get anything.
I think the basic explanation is that I write a fair amount of C, but almost all of it recreationally, so I have time to pause and wonder "what would happen if I do *that*"?
Once again, I'm learning new things about C! I got the typedef, but was unfamilar with either the GNU extension for needless puts declarations or the C99 BASIC feature :-) TIL! This series is fun, I'm looking forward to the next installment.
If you're curious about my remark that the function typedef is useless, it's because you can't use it for definitions, just for declarations. You can do this:
typedef int functype(char* x);
functype myfunc;
...and it's essentially equivalent to:
int myfunc(char* x);
...but then you still need to define myfunc() "manually" by restating the parameters and the return value. This won't work:
typedef int functype(char* x);
functype myfunc {
puts("Hello world");
}
"Three expressions are still required by the compiler, but in C, there is an implicit semicolon after a function definition (void _() { })."
No, there's no implicit semicolon. The syntax for a for statement (as of C23) is:
for ( expression[opt] ; expression[opt] ; expression[opt] ) secondary-block
for ( declaration expression[opt] ; expression[opt] ) secondary-block
The second form allows a declaration (typically something like "int i = 0;" in place of the first expression. But there's no semicolon after the "declaration" term in the second form -- because most declarations provide their own semicolons. For example, "int i" is not syntactically a declaration, but "int i;" is.
gcc appears to be treating a function *definition* as a *declaration*. As far as I can tell, that's incorrect (though of course gcc can do anything it likes as an extension).
There was a change in this area between C17 and C23. C17 has a constraint: "The declaration part of a for statement shall only declare identifiers for objects having storage class auto or register." C23 dropped that constraint.
And even if we assume that a function definition is a declaration, the program still violates a constraint. If you compile with "-std=c23 -pedantic-errors", gcc complains "error: ISO C forbids nested functions".
Ah, yeah. I saw that part of the spec after discussing this example on Mastodon beforehand. But I explained it a lot worse than you did. By "implicit semicolon", I meant that a function definition doesn't require an explicit semicolon at the end. But that's a boneheaded and inaccurate way to express it.
Thanks for a proper analysis. I edited the text to better capture the gist of this, I think.
Have you looked at Duff's Device? It weaves a do/while loop into a switch statement. It's the earliest example of C language abuse I learned about (and it wasn't theoretical, Duff actually used it as an optimization).
https://en.wikipedia.org/wiki/Duff%27s_device
Delightfully ç̶̼͇̘̱̫͋̂̇u̷̧͕̻̤̍̀̽̀̆͜r̸̪̦̣̥̣̆̈́̉̒̔̐̓ș̷͓̯̭͈͈͕̃̇ĕ̶̡̙̫̽͊̔̄ḑ̸̢͖̦͎̱̦̆. Love-hated it!
Totally degen, loved it :) How come you are so familiar with all those arcane obscure specifications of the C standard? Had you been a business lawyer, you would be filthy rich right now, combining arcane loop-holes ad absurdum to get anything.
I think the basic explanation is that I write a fair amount of C, but almost all of it recreationally, so I have time to pause and wonder "what would happen if I do *that*"?
Once again, I'm learning new things about C! I got the typedef, but was unfamilar with either the GNU extension for needless puts declarations or the C99 BASIC feature :-) TIL! This series is fun, I'm looking forward to the next installment.