K&R2's implicit declaration of exit()
Author |
Message |
Daniel Barke #1 / 21
|
 K&R2's implicit declaration of exit()
In places, Kernighan & Ritchie 2nd ed. uses exit() without either #include'ing <stdlib.h> or explicitly declaring the function in their program source code. This is done in Section 7.6, "Error Handling - Stderr and Exit", and also in Section 8.3, "Open, Creat, Close, Unlink". As I understand it, this implicitly causes exit() to be declared as having return type int, even though exit() really has return type void. This seems as bad as (and no worse than) the "classic" mistake learners often make in defining main() with return type void, even though main() must have return type int. If I am right, I assume the implicit declaration of exit() with the wrong return type doesn't matter much, or even at all, on most systems. Or is there some "let-out" in the C language, to work around or even allow (apparent) implicit mis-declaration of functions that "traditionally" required no declaration? Just curious. Daniel Barker, Institute of Cell and Molecular Biology, Swann Building, King's Buildings, Mayfield Road, Edinburgh EH9 3JR UK --
|
Tue, 17 Apr 2001 03:00:00 GMT |
|
 |
Ari Lukumie #2 / 21
|
 K&R2's implicit declaration of exit()
Quote:
> In places, Kernighan & Ritchie 2nd ed. uses exit() without either > #include'ing <stdlib.h> or explicitly declaring the function in their > program source code. This is done in Section 7.6, "Error Handling - Stderr > and Exit", and also in Section 8.3, "Open, Creat, Close, Unlink".
Note that, besides not using <stdlib.h> (or, at one time it used to be in <process.h>) for exit, open, creat, close and unlink are not standard functions. This section is no doubt a reminiscent from times when there wasn't any ANSI/ISO C standards. Bare in mind that the 2nd ed is based on the original white book, ANSI information added. Not all of the non-ANSI stuff was removed, however. If you run this program through an ANSI-compatible compiler (without non-ANSI errors turned on): #include <stdio.h> int main(void) { printf("Hello\n"); exit(0); } the compiler should give you a warning such as 'exit undefined, assuming extern returning int'. Since, in the old "prototypeless" world, a function could be declared as: exit(); the compiler won't complain about the argument to it, either. The only place where you actually had to write the arguments in such a case, was with variadic functions, for example: var_func(int, ...); Quote: > As I understand it, this implicitly causes exit() to be declared as having > return type int, even though exit() really has return type void. This > seems as bad as (and no worse than) the "classic" mistake learners often > make in defining main() with return type void, even though main() must > have return type int. > If I am right, I assume the implicit declaration of exit() with the wrong > return type doesn't matter much, or even at all, on most systems.
Not actually. If your program tries to *use* the returned value from exit, there may be a design problem in the program... As the function of exit is to exit the program, the return value doesn't matter much. The program flow should not continue after a call to exit (if you don't count atexit stuff). Anyway, you have probably run into a situation where you won't use the return value at all, even if it exists. For example: printf("Hello\n"); By definition, printf returns the number of characters it printed (an int), but how many of us make use of that information? Perhaps some don't even know that printf *has* a return value. Quote: > Or is there some "let-out" in the C language, to work around or even allow > (apparent) implicit mis-declaration of functions that "traditionally" > required no declaration?
Traditionally, the function argument types and return values defaulted to int. Even the syntax was slightly different. For a function body example: memcmp(m1, m2, len) /* no dec. needed for retvalue int */ char *s1; char *s2; /* no declaration needed for len, since it's int */ { ... } This changed along with ANSI that borrowed so-called prototypes from C++, as here: int memcmp(char *s1, char *s2, int len) { ... } (ok, this particular function also uses const and size_t nowadays...) To support older programs, many compilers still accept the implicit declarations. In practice, however, don't you use them but use explicit prototyping. Some compilers have switches you can use to make the compiler complain about the old use. In the future (when?) I believe that the implicit declarations will be dropped. AriL -- Humans may send email (if absolutely necessary) to the obvious non-spam address. --
|
Wed, 18 Apr 2001 03:00:00 GMT |
|
 |
Alan L. Folsom, Jr #3 / 21
|
 K&R2's implicit declaration of exit()
Quote:
> In places, Kernighan & Ritchie 2nd ed. uses exit() without either > #include'ing <stdlib.h> or explicitly declaring the function in their > program source code. This is done in Section 7.6, "Error Handling - Stderr > and Exit", and also in Section 8.3, "Open, Creat, Close, Unlink". > As I understand it, this implicitly causes exit() to be declared as having > return type int, even though exit() really has return type void. This > seems as bad as (and no worse than) the "classic" mistake learners often > make in defining main() with return type void, even though main() must > have return type int.
I'll let others comment on the legality of not declaring exit. There is a fundamental difference exit and main -- I cannot think of a case where the return value of exit might make a difference, but the return value from main can be, and is often, used. --
|
Wed, 18 Apr 2001 03:00:00 GMT |
|
 |
Dan P #4 / 21
|
 K&R2's implicit declaration of exit()
Quote: >In places, Kernighan & Ritchie 2nd ed. uses exit() without either >#include'ing <stdlib.h> or explicitly declaring the function in their >program source code. This is done in Section 7.6, "Error Handling - Stderr >and Exit", and also in Section 8.3, "Open, Creat, Close, Unlink". >As I understand it, this implicitly causes exit() to be declared as having >return type int, even though exit() really has return type void. This >seems as bad as (and no worse than) the "classic" mistake learners often >make in defining main() with return type void, even though main() must >have return type int.
Indeed. Both are cases of invoking undefined behaviour. Quote: >If I am right, I assume the implicit declaration of exit() with the wrong >return type doesn't matter much, or even at all, on most systems.
This is true. Only implementations using a different calling mechanism for void functions vs int functions are likely to be affected. Quote: >Or is there some "let-out" in the C language, to work around or even allow >(apparent) implicit mis-declaration of functions that "traditionally" >required no declaration?
No such thing. The authors of K&R2 have, most likely, simply reused the code from K&R1, where exit() is an int function (because there are no void functions in K&R C) and doesn't require an explicit declaration. Dan -- Dan Pop CERN, IT Division
Mail: CERN - EP, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland --
|
Wed, 18 Apr 2001 03:00:00 GMT |
|
 |
Jim Mellande #5 / 21
|
 K&R2's implicit declaration of exit()
Quote:
> In places, Kernighan & Ritchie 2nd ed. uses exit() without either > #include'ing <stdlib.h> or explicitly declaring the function in their > program source code. This is done in Section 7.6, "Error Handling - Stderr > and Exit", and also in Section 8.3, "Open, Creat, Close, Unlink". > As I understand it, this implicitly causes exit() to be declared as having > return type int, even though exit() really has return type void. This > seems as bad as (and no worse than) the "classic" mistake learners often > make in defining main() with return type void, even though main() must > have return type int. > If I am right, I assume the implicit declaration of exit() with the wrong > return type doesn't matter much, or even at all, on most systems. > Or is there some "let-out" in the C language, to work around or even allow > (apparent) implicit mis-declaration of functions that "traditionally" > required no declaration? > Just curious. > Daniel Barker, > Institute of Cell and Molecular Biology, > Swann Building, > King's Buildings, > Mayfield Road, > Edinburgh > EH9 3JR > UK > --
In this one case, I would assume that it scarcely matters, since exit() is guaranteed to *not* return, thus the return value (if any) is irrelevant. --
|
Wed, 18 Apr 2001 03:00:00 GMT |
|
 |
Pierre Assel #6 / 21
|
 K&R2's implicit declaration of exit()
Quote:
>In places, Kernighan & Ritchie 2nd ed. uses exit() without either >#include'ing <stdlib.h> or explicitly declaring the function in their >program source code. This is done in Section 7.6, "Error Handling - Stderr >and Exit", and also in Section 8.3, "Open, Creat, Close, Unlink". >As I understand it, this implicitly causes exit() to be declared as having >return type int, even though exit() really has return type void.
Nitpick: exit() doesn't return. It's hard to imagine an implementation that cares about its declared return type. (This doesn't invalidate your question, though.) -- --Pierre Asselin, Westminster, Colorado
--
|
Wed, 18 Apr 2001 03:00:00 GMT |
|
 |
Auke Reits #7 / 21
|
 K&R2's implicit declaration of exit()
Quote: > In places, Kernighan & Ritchie 2nd ed. uses exit() without either > #include'ing <stdlib.h> or explicitly declaring the function in their > program source code. This is done in Section 7.6, "Error Handling - Stderr > and Exit", and also in Section 8.3, "Open, Creat, Close, Unlink". > As I understand it, this implicitly causes exit() to be declared as having > return type int, even though exit() really has return type void. This
Correct. Quote: > seems as bad as (and no worse than) the "classic" mistake learners often > make in defining main() with return type void, even though main() must > have return type int.
I don't think so. Quote: > If I am right, I assume the implicit declaration of exit() with the wrong > return type doesn't matter much, or even at all, on most systems.
If the return value is not used (and if I am right) any wrong declaration of a function's type does not really matter. However, if the value IS used, a wrong type may cause problems. Then note that the return value of main usually is used by the startup (and termination) code And note that I will be wrong when the implementation uses some temporary storage for the return value which needs to be cleaned up by the caller. I don't know of any implementations like that though ;-) For the specific case of exit(), any return value would have no meaning anyway as it does not ever return. Greetings from _____ /_|__| Auke Reitsma, Delft, The Netherlands. / | \ ------------------------------------- Remove NO_SPAM_ from my address ... --
|
Wed, 18 Apr 2001 03:00:00 GMT |
|
 |
Gene Wirchen #8 / 21
|
 K&R2's implicit declaration of exit()
Quote:
>> In places, Kernighan & Ritchie 2nd ed. uses exit() without either >> #include'ing <stdlib.h> or explicitly declaring the function in their >> program source code. This is done in Section 7.6, "Error Handling - Stderr >> and Exit", and also in Section 8.3, "Open, Creat, Close, Unlink". >> As I understand it, this implicitly causes exit() to be declared as having >> return type int, even though exit() really has return type void. This >Correct. >> seems as bad as (and no worse than) the "classic" mistake learners often >> make in defining main() with return type void, even though main() must >> have return type int. >I don't think so.
Except for freestanding implementations, main() must return int. Quote: >> If I am right, I assume the implicit declaration of exit() with the wrong >> return type doesn't matter much, or even at all, on most systems. >If the return value is not used (and if I am right) any wrong declaration >of a function's type does not really matter. However, if the value IS >used, a wrong type may cause problems. Then note that the return value of >main usually is used by the startup (and termination) code
Possibly, this applies to exit()'s return value as well (unless someone has chapter and verse on what is to be done w.r.t. to return codes when exit() is called). Quote: >And note that I will be wrong when the implementation uses some temporary >storage for the return value which needs to be cleaned up by the caller. I >don't know of any implementations like that though ;-)
The gotcha stealthily pads through the thick jungle of C code. It isn't hungry *now*, but when your guard is down, you'll be irresistably tasty. Quote: >For the specific case of exit(), any return value would have no meaning >anyway as it does not ever return.
It causes the program to return to the operating system. Any value might have context there. Sincerely, Gene Wirchenko Computerese Irregular Verb Conjugation: I have preferences. You have biases. He/She has prejudices. --
|
Fri, 20 Apr 2001 03:00:00 GMT |
|
 |
Dan P #9 / 21
|
 K&R2's implicit declaration of exit()
Quote: >If the return value is not used (and if I am right) any wrong declaration >of a function's type does not really matter.
You're wrong. It is a case of undefined behaviour, whether the return value is used or discarded. You must be confusing this situation with the following: int foo(){} It is correct to call foo if you discard its return value, but you invoke undefined behaviour if you attempt to use the return value, which is indeterminate. Calling a function whose declaration is incompatible with its definition is always and unconditionally undefined behaviour: If the function is defined with a type that is not compatible with the type (of the expression) pointed to by the expression that denotes the called function, the behavior is undefined. As we all know, int and void are not compatible types. Dan -- Dan Pop CERN, IT Division
Mail: CERN - EP, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland --
|
Fri, 20 Apr 2001 03:00:00 GMT |
|
 |
telnet us #10 / 21
|
 K&R2's implicit declaration of exit()
Quote:
> In this one case, I would assume that it scarcely matters, since exit() > is guaranteed to *not* return, thus the return value (if any) is > irrelevant.
It isn't strictly true that it is ok to misdeclare the return value just because the return value isn't used. Nothing in the C standard prevents an implementation from having the following calling conventions: void foo(int x) ----> x in argument 1 slot on "stack" int foo(int x) ----> (int *) pointer to result in slot 1 x in slot 2 on such a system, the best you could hope for is that exit() would get the wrong value. If it didn't crash first from not having the stack set up like it expected. --------------------------------------------------------------------------- Tim Hollebeek | "Everything above is a true
URL: http://wfn-shop.princeton.edu/~tim | false values of true." --
|
Fri, 20 Apr 2001 03:00:00 GMT |
|
 |
Francis Glassboro #11 / 21
|
 K&R2's implicit declaration of exit()
Quote: > Possibly, this applies to exit()'s return value as well (unless >someone has chapter and verse on what is to be done w.r.t. to return >codes when exit() is called).
??? the prototype for exit is: void exit(int status); It is that parameter that means main must return an int (it could have been relaxed to something convertible to an int) However note that there is very little you could do with the return value of exit:) Francis Glassborow Chair of Association of C & C++ Users 64 Southfield Rd Oxford OX4 1PA +44(0)1865 246490 All opinions are mine and do not represent those of any organisation --
|
Fri, 20 Apr 2001 03:00:00 GMT |
|
 |
Mike Albau #12 / 21
|
 K&R2's implicit declaration of exit()
: Possibly, this applies to exit()'s return value as well (unless : someone has chapter and verse on what is to be done w.r.t. to return : codes when exit() is called). : >And note that I will be wrong when the implementation uses some temporary : >storage for the return value which needs to be cleaned up by the caller. I : >don't know of any implementations like that though ;-) : The gotcha stealthily pads through the thick jungle of C code. : It isn't hungry *now*, but when your guard is down, you'll be : irresistably tasty. Interestingly enough, in a thread on comp.arch recently, a subroutine-calling sequence (for a not-quite-hypothetical CPU) which _would_ run afoul of void/int return mismatch was proposed. In addition various stack machines through the ages have used a similar scheme, which consists of reserving a "parameter" slot on the stack for the return value. Depending on whether thsi slot was "before" or "after" the PC, all sorts of havoc could ensue from the mismatch. OK, in the _particular_ case of exit(), the most likely result would be that the wrong exit value would be used (because gotten from the wrong stack offset), but exit may also be confused about its caller's return address. It's not going to return, but (especially if you are returning an errror, or it thinks you are) it mighty want to print a helpful error message indicating where it was called. I have to agree with Gene: Don't lie to your compiler. It will get its revenge later, or one of its relatives will. :-) BTW: someone mentioned "in the old days" only declaring variadic functions. Without naming names, in the not-so-old-days, a certain major vendor declared _no_ functions that returned int in the standard headers. Not even variadic functions like printf(). Yeah, I almost vomitted too... Mike
--
|
Fri, 20 Apr 2001 03:00:00 GMT |
|
 |
Tom Tor #13 / 21
|
 K&R2's implicit declaration of exit()
Alan L. Folsom, Jr. wrote in a message to Daniel Barker: ALFJ> I cannot think of a case where the return value of exit might ALFJ> make a difference, Well, assuming the function my_exit() returns nonzero on success or 0 on failure, something like this could be considered reasonable: if (!my_exit()) { some_logging_function("Program was unable to terminate properly!\ n" "Rebooting..."); if (!system_specific_reboot_function()) { /* panic! */ } } greetings, Tom
--
|
Fri, 20 Apr 2001 03:00:00 GMT |
|
 |
Auke Reits #14 / 21
|
 K&R2's implicit declaration of exit()
Quote:
> I have to agree with Gene: Don't lie to your compiler. > It will get its revenge later, or one of its relatives will. :-)
Well, I never do. But I still think that lying about the type of an unused return value is less dangerous than lying about a used return value. Also I'd still like to have references to the proper parts of the standard w.r.t. this 'problem'. I've looked of course -- but no luck ... BTW, I of course admit that I was wrong ;-) Greetings from _____ /_|__| Auke Reitsma, Delft, The Netherlands. / | \ ------------------------------------- Remove NO_SPAM_ from my address ... --
|
Tue, 24 Apr 2001 03:00:00 GMT |
|
 |
Gene Wirchen #15 / 21
|
 K&R2's implicit declaration of exit()
Quote:
>> Possibly, this applies to exit()'s return value as well (unless >>someone has chapter and verse on what is to be done w.r.t. to return >>codes when exit() is called). >??? the prototype for exit is: >void exit(int status); >It is that parameter that means main must return an int (it could have >been relaxed to something convertible to an int) >However note that there is very little you could do with the return >value of exit:)
Given a friendly standard, you could use it the same as the return value from main(). exit() would then be a very quick return to the OS and the program would have a return code. Sincerely, Gene Wirchenko Computerese Irregular Verb Conjugation: I have preferences. You have biases. He/She has prejudices. --
|
Tue, 24 Apr 2001 03:00:00 GMT |
|
|
Page 1 of 2
|
[ 21 post ] |
|
Go to page:
[1]
[2] |
|