Function without a "return type"?
Author |
Message |
Morris Dove #1 / 9
|
 Function without a "return type"?
6.2.5[20] A function type describes a function with specified return type. A function type is characterized by its return type and the number and types of its parameters. A function type is said to be derived from its return type, and if its return type is T, the function type is sometimes called function returning T. The construction of a function type from a return type is called function type derivation. 7.20.4.3[1] Synopsis #include <stdlib.h> void exit(int status); 7.20.4.3[6] The exit function cannot return to its caller. ----- Seems to me that the standard offers no appropriate "function type" for exit() [or abort or _Exit] and that the specified prototype is misleading since exit() is a function which doesn't return rather than a function returning void (nothing). I think the "volatile" type qualifier would apply, but what about the type itself? None of the existing types would seem to apply since the notion of "return type" doesn't apply in any sense... Have I missed something? -- Morris Dovey West Des Moines, Iowa USA
|
Sat, 06 Dec 2003 00:40:06 GMT |
|
 |
Joe Mau #2 / 9
|
 Function without a "return type"?
Quote:
> 6.2.5[20] A function type describes a function with specified > return type. A function type is characterized by its return type > and the number and types of its parameters. A function type is > said to be derived from its return type, and if its return type > is T, the function type is sometimes called function returning > T. The construction of a function type from a return type is > called function type derivation. [...] > Seems to me that the standard offers no appropriate "function > type" for exit() [or abort or _Exit] and that the specified > prototype is misleading since exit() is a function which doesn't > return rather than a function returning void (nothing).
I'm not sure I understand your point. It's clear from the section you quoted that a "function derived from type" doesn't have to return that type, it merely has to /specify/ that return type. Nowhere does it say that a function actually has to return the specified type. Note the careful wording above "is sometimes called a function returning T", which clearly (to me, at least) were chosen to mean that it doesn't have to return that type, but is merely sometimes *called* "function returning T". In fact, in order to have a different type for functions that never return, a function type would sometimes change depending on the contents of a different function, which I am not sure is a good idea at all. Consider: void somefunc(void) { if(1) exit(0); } void somefunc2(void) { if(UserHasTypedFoo()) return; else somefunc(); } int foo(void) { somefunc2(); } What type is "foo"? Does it change if you add `while(1);` before calling somefunc2()? Does the type change at runtime depending if the user types "foo"? How about if you change the body of somefunc() to `if(OpSysMsg()) exit(0);`? Does it matter that OpSysMsg() can never return 0? -- Joe Maun Montreal, QC Canada
|
Sat, 06 Dec 2003 03:41:08 GMT |
|
 |
Morris Dove #3 / 9
|
 Function without a "return type"?
Quote:
> I'm not sure I understand your point. It's clear from the section you > quoted that a "function derived from type" doesn't have to return that > type, it merely has to /specify/ that return type. Nowhere does it say > that a function actually has to return the specified type. Note the > careful wording above "is sometimes called a function returning T", > which clearly (to me, at least) were chosen to mean that it doesn't have > to return that type, but is merely sometimes *called* "function > returning T". > In fact, in order to have a different type for functions that never > return, a function type would sometimes change depending on the contents > of a different function, which I am not sure is a good idea at all. > Consider: > void somefunc(void) { > if(1) exit(0); > } > void somefunc2(void) { > if(UserHasTypedFoo()) > return; > else > somefunc(); > } > int foo(void) { > somefunc2(); > } > What type is "foo"? Does it change if you add `while(1);` before calling > somefunc2()? Does the type change at runtime depending if the user types > "foo"? How about if you change the body of somefunc() to `if(OpSysMsg()) > exit(0);`? Does it matter that OpSysMsg() can never return 0?
Joe... foo() should return an int. Otherwise I think I don't disagree with you. I was called (I think correctly) on a constraint violation in the "exit(1)" thread and have been having a severe case of "intellectual indigestion" since. It still seems reasonable and unambiguous to me to code "UserHasTypedFoo() || exit(EXIT_FAILURE);" because I know that the "or" will never be performed; and that exit's function type is immaterial. Tak-Shing Chan pointed out that this was a constraint violation because of the exit's standard-defined function type of void. I've never used this construct in my own code but can't imagine why the constraint violation /need/ be applied. I think what I'm looking for is some was of informing the compiler that the function type is immaterial because of the function's terminal nature and so remove the constraint violation. Of course, we can spoof the compiler be hiding the exit() call in an int wrapper; but my feeling is that spoofing the compiler is questionable practice. -- Morris Dovey West Des Moines, Iowa USA
|
Sat, 06 Dec 2003 04:29:55 GMT |
|
 |
Kaz Kylhe #4 / 9
|
 Function without a "return type"?
Quote:
>6.2.5[20] A function type describes a function with specified >return type. A function type is characterized by its return type >and the number and types of its parameters.
Which rules out the existence of the entity alluded to in your subject line, namely a function without a return type. Quote: >A function type is >said to be derived from its return type, and if its return type >is T, the function type is sometimes called function returning >T. The construction of a function type from a return type is >called function type derivation. >7.20.4.3[1] Synopsis > #include <stdlib.h> > void exit(int status); >7.20.4.3[6] The exit function cannot return to its caller. >----- >Seems to me that the standard offers no appropriate "function >type" for exit() [or abort or _Exit] and that the specified >prototype is misleading since exit() is a function which doesn't >return rather than a function returning void (nothing).
You are confusing the act of executing return, with the function's return type. Quote: >I think the "volatile" type qualifier would apply, but what about
In what way? This qualifier gives some special semantics to object accesses. Functions are not objects. Quote: >the type itself? None of the existing types would seem to apply >since the notion of "return type" doesn't apply in any sense... >Have I missed something?
Yes, that the return type is still useful for constraint checking. int x = exit(0); /* error, assignment of void to int */ Also, what about: #include <stdlib.h> int main(void) { exit(0); } Here, main does not return. So does main not have a return type? What about an expression that is never evaluated; does that also not have a type? if (0) { 3; /* this expression has type int */ } There are languages in which the return type is determined from the value that is actually returned, or an expression's type is determined by the value that it yields, but C isn't one of them.
|
Sat, 06 Dec 2003 06:43:11 GMT |
|
 |
Kaz Kylhe #5 / 9
|
 Function without a "return type"?
Quote:
>It still seems reasonable and unambiguous to me to code "UserHasTypedFoo() >|| exit(EXIT_FAILURE);" because I know that the "or" will never be >performed; and that exit's function type is immaterial.
However, if the function is called, then its type matters, consider: /* no <stdlib.h> included */ { extern int exit(int); /* note incorrect declaration */ exit(0); /* undefined behavior */ The return type of a function is part of its type. Two function types are incompatible if they do not specify the same return type, and using an incompatible expression to call a function causes undefined behavior, even if the incompatibility is in the return value, and the called function does not return. Quote: >I've never used this construct in my own code but can't imagine why the >constraint violation /need/ be applied. I think what I'm looking for is some >was of informing the compiler that the function type is immaterial because >of the function's terminal nature and so remove the constraint violation.
This is simply a consequence of the || operator requiring operands that are scalar types. The type void is not scalar, hence the constraint violation. You could apply the same argument to syntax errors. For instance: if (0) { never executed } Now if we could only inform the compiler that the stuff between the braces is never executed, and so the syntax doesn't matter. ;) Quote: >Of course, we can spoof the compiler be hiding the exit() call in an int >wrapper; but my feeling is that spoofing the compiler is questionable >practice.
You can make that wrapper explicit, by using the comma operator: UserHasTypedFoo() || (exit(EXIT_FAILURE), 0); The comma operator can happily take a type void on the left and int on the right. The result type is that of the right hand expression, which satisfies the || operator's need for a scalar type.
|
Sat, 06 Dec 2003 06:56:12 GMT |
|
 |
Richard B #6 / 9
|
 Function without a "return type"?
Quote:
> I've never used this construct in my own code but can't imagine why the > constraint violation /need/ be applied. I think what I'm looking for is some > was of informing the compiler that the function type is immaterial because > of the function's terminal nature and so remove the constraint violation.
I think the main problem with this is that you could write a function that _may_ never return, state that it does not return, and then have a program that is conformant if and only if you solve the halting problem. Richard
|
Sat, 06 Dec 2003 19:50:52 GMT |
|
 |
Morris Dove #7 / 9
|
 Function without a "return type"?
Quote:
> > I've never used this construct in my own code but can't imagine why the > > constraint violation /need/ be applied. I think what I'm looking for is some > > was of informing the compiler that the function type is immaterial because > > of the function's terminal nature and so remove the constraint violation. > I think the main problem with this is that you could write a function > that _may_ never return, state that it does not return, and then have a > program that is conformant if and only if you solve the halting problem.
Thanks, Richard... I'd not even considered that aspect of the problem -- every now and then some "feature" (or lack thereof) of C gets under my skin and sends me off on a tangent to "find a better way". It's almost always -- as here -- a learning experience for me. Thanks to all who responded. -- Morris Dovey West Des Moines, Iowa USA
|
Sat, 06 Dec 2003 23:27:15 GMT |
|
 |
Ben Pfaf #8 / 9
|
 Function without a "return type"?
Quote:
> It still seems reasonable and unambiguous to me to code "UserHasTypedFoo() > || exit(EXIT_FAILURE);" because I know that the "or" will never be > performed; and that exit's function type is immaterial. Tak-Shing Chan > pointed out that this was a constraint violation because of the exit's > standard-defined function type of void. > I've never used this construct in my own code but can't imagine why the > constraint violation /need/ be applied. I think what I'm looking for is some > was of informing the compiler that the function type is immaterial because > of the function's terminal nature and so remove the constraint violation.
Some compilers provide a special extension to declare that a function will never return. This allows for better warnings and sometimes better optimization, too. For instance, GCC allows functions to be declared as __attribute__ ((noreturn)); -- "When I have to rely on inadequacy, I prefer it to be my own." --Richard Heathfield
|
Sat, 06 Dec 2003 23:36:28 GMT |
|
 |
Richard B #9 / 9
|
 Function without a "return type"?
Quote:
> > I think the main problem with this is that you could write a function > > that _may_ never return, state that it does not return, and then have a > > program that is conformant if and only if you solve the halting problem. > I'd not even considered that aspect of the problem -- every now and then some > "feature" (or lack thereof) of C gets under my skin and sends me off on a tangent > to "find a better way".
Same here... Quote: > It's almost always -- as here -- a learning experience for me.
...and same here! Richard
|
Sun, 07 Dec 2003 14:58:09 GMT |
|
|
|