|
Had heard more than 20 years ago, that having a return statement at the end of a void function in C++ was indeed a harmless thing; the compiler wouldn't complain, and things would work just fine. Just that some programmers prefer to have a return in every function they write.
|
|
|
|
|
Maximilien wrote: Was it necessary at some point in time ? Necessary, no. Used, yes, back in the day probably because people were used mostly with FORTRAN where each function and "subroutine" needed at least one return statement.
Mircea
|
|
|
|
|
Maximilien wrote: Was it necessary at some point in time ?
Both forms are specifically allowed then and now.
From "C Programming Language" 2nd Edition (oldest I have and copyright is 1978.)
"A function need not return a value; a return statement with no expression causes control, but no useful value, to be returned to the caller, as does "falling off the end" of a function by reaching the terminating right brace."
Possible though that earlier compilers required it.
More likely though that someone liked one form or the other. Perhaps even forced that on others.
Requiring it would be fallout from methods with a return value. Older compilers would not warn on exit without a value for those. So the calling method would then end up with whatever garbage was on the call stack.
I did not find the same syntax in "The C++ Programming Language Special Edition" (Copyright 2000) but I didn't look all that hard.
There are however examples that provide two different void functions. One which exits with return and one which does not. So works for C++ also.
-----------------------------------------------------
Just for fun this is LEGAL as documented in the C++ book above.
void g(int* p);
void h(int* p) { return g(p); }
Text explains that is needed for templates.
But if I was reviewing code and saw that anywhere but a template I would mark it as an error.
|
|
|
|
|
jschell wrote: Possible though that earlier compilers required it.
You remind me that my first introduction to C was with Whitesmith C (on a VAX), and maybe that could have required it.
|
|
|
|
|
jschell wrote:
void h(int* p) { return g(p); } Yuck. That's deceptive to me, as it makes it look like g(p) returns a value. I'd prefer writing it like this:
void h(int* p)
{
g(p);
return;
}
Software Zen: delete this;
|
|
|
|
|
Actually, if g(p) returns void, then this is definitely allowed. Makes generic programming easier, with less boilerplate, and faster compilation. Not sure what is supposed to happen if g(p) is something other than void - it should really be a syntax error.
|
|
|
|
|
Unsure, maybe, C back in the 80s. Or Pascal? But I always make sure each and every C function (or C# Method) has exactly one return statement. (I think I've written only one C# Method with more than one return, but that was an unusual situation.)
I agree that it "shows intent". Or potentially may help with debugging, though that's not usually critical either.
At the very least you know that it was written by a developer who has a long history of development, not one of these kids who is only interested in doing the absolute minimum and can't be trusted.
|
|
|
|
|
Quote: But I always make sure each and every C function (or C# Method) has exactly one return statement.
I followed the same for nearly 30 years.
Meanwhile I switched at least for 'void methods' to return imediatelly something does not fit. This to avoid 'nested if'
Still I'm fighting with that when a method needs to return a value. Here I stay with the pattern to have only _one_ return....
|
|
|
|
|
I believe it never was, as it was meant to be more or less compatible with C code, which doesn't require it.
Interestingly you can call main() from inside your C app, but not in C++.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
honey the codewitch wrote: Interestingly you can call main() from inside your C app, but not in C++. Really? I didn't know that.
I'll admit it's probably not a good idea, and there are easy ways around the prohibition, ... Hmm. I think I've figured some of it out.- There are multiple valid forms of
main(...) , and implementation-defined arguments are allowed. Allowing calls to it might require too much special case handling between the compiler and linker to ensure a match between the call and the actual implementation. - Another factor might be runtime initialization that takes place in
main() 's prolog. - Objects declared
static could potentially call main() before it had been called for the actual application startup. Sounds like the prohibition is a good way to make the compiler, linker, and runtime initialization job easier.
Software Zen: delete this;
|
|
|
|
|
Part of it might be static initialization behavior in C++ precludes it, but I don't know enough about the machinations of all that to be certain of anything.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
This piece of code
int main()
{
main();
} compiles fine. Anyway, I didn't try to run the executable.
"In testa che avete, Signor di Ceprano?"
-- Rigoletto
|
|
|
|
|
Hmm, well I've never actually tried it. I was relying on a lecture on C++.
I doubt it's standard though. I'm pretty sure dude knew what he was on about. He wasn't a nobody, but I forget his title.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
It looks 'the dude' was right. The C++ standard doesn't allow to call main recursively (and states that main 'shall not be used within a program').
Nevertheless, g++ allows that. You have to use -pedantic in order to get a warning.
"In testa che avete, Signor di Ceprano?"
-- Rigoletto
|
|
|
|
|
I don't remember his name and couldn't find the video at gunpoint so "the dude" abides.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
Agree. Such a requirement would break C compatibility.
"If we don't change direction, we'll end up where we're going"
|
|
|
|
|
honey the codewitch wrote: Interestingly you can call main() from inside your C app, but not in C++.
Odd.
Took me a bit to find a reference. Following seems to be best I could find.
Use the index to find '3.6' the click on page number. The first section there is the relevant one.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
"The function main shall not be used within a program. The linkage(3.5) of main is implementation-defined.
A program that defines main as deleted or that declares main to be inline, static, or constexpr is ill-formed. The name main is not otherwise reserved."
Although a draft I did find other mentions to this so I suspect is it substantially correct. Also other references suggest the updated spec matches (2014 to C14).
However I think the language of that is not as precise as some might think.
Since the linkage is not defined that means a compiler is free to do whatever it wants with it.
And the easiest way to handle that is to link it. Why? Because if it doesn't link it then it must figure out that the specific function is in fact the real entry point versus some other legitimate variation. Easier to just ignore the issue - which is allowed.
Also note that this restriction was added with newer versions of the spec. The original ANSI spec did not have any subsections in 3.6 at all.
-------------------------------------------------
Found the following also. See the second reply.
https://stackoverflow.com/questions/2128321/can-main-function-call-itself-in-c[^]
I didn't verify that one but the response suggests that the compiler is not responsible for telling you that you should not be calling main.
That is another one of things that as a compiler writer should not worry about. There are other things they should spend their time on to get right.
|
|
|
|
|
I hate the specs. They read like bad stereo instructions.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
To be fair though they do provide exactness. Especially the C and C++ ones. I know the Java one has numerous simple documented errors which have remained in place in all versions.
|
|
|
|
|
I doubt the language ever required it, but maybe some “lint” programs had that as a setting?
“Ensure there is at least one return statement for every function”
It would help catch the undefined return value if you forgot the return statement.
I could see a first generation lint program complaining of a missing return on a void function.
|
|
|
|
|
Maybe it's tag that has meaning only to the "creator". Mine are leftovers from extending a function then changing my mind.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
Sorry I was under the impression that
int fn(){
int a;
return(0);
} was K&R, the cooler
void fn
{
int a;
} I though one the rules was 'thou shalt return a value!'
Glenn
|
|
|
|
|
In the C89 standard draft (the actual standard you have to buy).
Shows that return has never been required....minimalist approach...
https://port70.net/%7Ensz/c/c89/c89-draft.html#3.2.2.2
3.6.6.4 The return statement
...
Reaching the } that terminates a function is equivalent to executing a return statement without an expression.
|
|
|
|
|
mdblack98 wrote: Reaching the } that terminates a function is equivalent to executing a return statement without an expression.
My copy of the 1978 C reference manual contains the equivalent statement:
"Flowing off the end of a function is equivalent to a return with no returned value."
It also said that if 'return;' form is used, the returned value is undefined. The absence of a type declarator was assumed to mean 'int'. At that time there was no 'void' keyword. So, no need to search earlier than 1978 for the complete answer.
|
|
|
|
|
One of my first surprises (in the 90's) going from C++ to C, was that void was never used to define the return value of a main function. C++ had, at that point, always meant to be a superset of C and so had many odd things you wouldn't see in C for years (like variable declarations anywhere in the function).
My understanding was that C was always supposed to return a value to the operating system as an integer, regardless of what you did. So when C++ introduced void as a return type, even for main, I guess it was up in the air what you did in the end (that book has since been lost to a basement flooding so I can't remember or look up how it recommended to end the main function)
|
|
|
|