ark@alice.UUCP (Andrew Koenig) (05/22/90)
In article <1231@wet.UUCP>, noah@wet.UUCP (Noah Spurrier) writes: > I get the bad feeling that I am going to get flamed for this... But I can > see no reason why my Turbo C compiler does not like the way I prototype > the following program. > /* Protoypte */ > void x (float); /* ... */ > void x (y) > float y; > { > printf ("%f",y); > } You should do it this way: void x(float y) { printf("%f",y); } The point is that old-style parameter declarations are decidedly not equivalent to new-style declarations. For compatibility reasons, it must be legal to define void x(y) float y; { /* ... */ } and call it from a separately compiled module without any declaration there at all. That means it must be capable of accepting a double parameter. Thus, in effect, this least example is equivalent to: void x(double dummy) { float y = dummy; /* ... */ } In other words, if you want to use ANSI-style function prototypes, you must use them consistently. -- --Andrew Koenig ark@europa.att.com
mercer@ncrstp.StPaul.NCR.COM (Dan Mercer) (05/25/90)
In article <1231@wet.UUCP> noah@wet.UUCP (Noah Spurrier) writes: : : :I get the bad feeling that I am going to get flamed for this... But I can :see no reason why my Turbo C compiler does not like the way I prototype :the following program. : :#include <stdio.h> : :/* Prototype */ :void x (float); : :void main () :{ : x ((float)1); :} : :void x (y) :float y; :{ : printf ("%f",y); :} : :I keep getting a type mismatch error in function x() parameter float y; :If I delete the prototype line the program works fine, but with warnings. : :Also just to make sure I was seeing straight I tried this nearly identical :program. : :#include <stdio.h> : :/* Protoypte */ :void x (int); : :void main () :{ : x (1); :} : :void x (y) :int y; :{ : printf ("%d",y); :} : :This works just fine, no warnings, no errors. Maybe I can't see the forest for :the trees, so I am hoping someone else can take a chain-saw to this one... :Oh if had only paid attention that day in class when they explain EXACTLY why :I can't do what I am trying to do. : :I hope anyone can help... : :yours, : :Noah Spurrier :noah@WET.UUCP Maybe try the following: /* Prototype */ void x (float); void main () { x ((float)1); } void x (float y) <======== change to ANSI declaration style { printf ("%f",y); } My Turbo C has a fit if I mix ANSI declarations with old style declarations (makes porting code a real bitch) -- Dan Mercer Reply-To: mercer@ncrstp.StPaul.NCR.COM (Dan Mercer)
throopw@sheol.UUCP (Wayne Throop) (05/29/90)
> I get the bad feeling that I am going to get flamed for this... No, but my reply may revive a long-forgotten flame-war... > But I can see no reason why my Turbo C compiler does not like > the way I prototype the following program. > [..paraphrasing.. > void x(float); > void main(){x(1.0);} > void x(v) float v; {} ..] Many people pointed out quite correctly that the forward declaration of the function disagrees with its definition later, because in old-style function definitions, float is promoted to double. The simplest way to fix it is to change the third line to something like > void x(float v){} However, nobody seems to have noticed the other type gaffe, namely > void main(){...} The function named "main" in C environments is not how, and has never been, of type (void ()). At the very least, it should be declared as returning an (int), and best of all is to declare it completely, with argc and argv and the whole nine yards. Remember: there is a contract with that fragment of your C environment that invokes the main routine (often called "crt0" for reasons unknown to me) which says that the routine will return an integer value. It is unwise to lie to the compiler in this way. -- Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw@rti.rti.org
darcy@druid.uucp (D'Arcy J.M. Cain) (05/31/90)
In article <0705@sheol.UUCP> throopw@sheol.UUCP (Wayne Throop) writes: >> I get the bad feeling that I am going to get flamed for this... >No, but my reply may revive a long-forgotten flame-war... > Yes but what else is Usenet for? :-) > [..] >However, nobody seems to have noticed the other type gaffe, namely > >> void main(){...} > >The function named "main" in C environments is not how, and has never been, >of type (void ()). At the very least, it should be declared as returning >an (int), and best of all is to declare it completely, with argc and argv and >the whole nine yards. > >Remember: there is a contract with that fragment of your C environment >that invokes the main routine (often called "crt0" for reasons unknown to me) >which says that the routine will return an integer value. It is unwise >to lie to the compiler in this way. But if you always use exit() to end your program, isn't it sort of lying to tell C that you will return an int? As I recall that previous "flame war" The problem with declaring main to return void was that the function startup sequence might be different for different or no returns. I can't recall if anyone actually came up with an ANSI C compiler that had this property but I am sure it is rare at best. I think that if any compiler acts this way it should handle the special case of main somehow. At the very least it should internally prototype main. The best way of handling it would be to use whatever the programmer declares to check return types but to set the function call as if it had been declared properly. So can anyone summarize the ANSI compilers (or K&R1 compilers for that matter) for which decalaring main to return void causes a problem? -- D'Arcy J.M. Cain (darcy@druid) | Government: D'Arcy Cain Consulting | Organized crime with an attitude West Hill, Ontario, Canada | (416) 281-6094 |
steve@taumet.COM (Stephen Clamage) (06/01/90)
In article <1990May31.135230.242@druid.uucp> darcy@druid.UUCP (D'Arcy J.M. Cain) writes: >So can anyone summarize the ANSI compilers (or K&R1 compilers for that >matter) for which decalaring main to return void causes a problem? The ANSI standard says that in a hosted environment, a strictly conforming program will define main as int main() { /* ... */ } or int main(int argc, char *argv[]) { /* ... */ } (The names argc and argv are not required by the standard, but you have to call the args something if they are declared.) A compiler may allow anything it wishes in addition, but programs depending on other defintions being legal may not be portable. As to "lying to the compiler" when you terminate via exit(), the standard says: "A return from the initial call to the _main_ function function is equivalent to calling the _exit_ function with the value returned by the _main_ function as its argument." So the compiler is not allowed to be upset when exit() does not return. I don't see any value in making lists of which detailed extensions are supported by which particular compilers. Compilers often accept (and reject) different extensions in different releases. Such a list becomes quickly unmanageable. Write for maximum portability and isolate unavoidable dependencies for easy fixing. -- Steve Clamage, TauMetric Corp, steve@taumet.com
darcy@druid.uucp (D'Arcy J.M. Cain) (06/02/90)
In article <236@taumet.COM> steve@taumet.UUCP (Stephen Clamage) writes: >In article <1990May31.135230.242@druid.uucp> darcy@druid.UUCP (D'Arcy J.M. Cain) writes: >>So can anyone summarize the ANSI compilers (or K&R1 compilers for that >>matter) for which decalaring main to return void causes a problem? > >As to "lying to the compiler" when you terminate via exit(), the >standard says: > "A return from the initial call to the _main_ function function > is equivalent to calling the _exit_ function with the value returned > by the _main_ function as its argument." >So the compiler is not allowed to be upset when exit() does not return. > I wasn't worried about exit() not returning. Rather the fact that there is no need to return from main if exit() is used to leave a program. In the following program: #include <stdio.h> int main(int argc, char **argv) { printf("%s has %d arguments\n", *argv, argc); exit(0); } The compiler will give a warning that a function (main) which should return an int does not return anything. If, like me, you prefer super quiet compiles you must add a return(0) statement. You now have added code (which won't be optimised out) which has no other purpose than to shut the compiler up. I will do that when necessary but try to avoid it whenever possible. Note that I realize that the exit above can be replaced by a return but this is a trivial example. In practice the exit may not even be in the main routine. -- D'Arcy J.M. Cain (darcy@druid) | Government: D'Arcy Cain Consulting | Organized crime with an attitude West Hill, Ontario, Canada | (416) 281-6094 |
steve@taumet.COM (Stephen Clamage) (06/04/90)
In article <1990Jun2.091606.9125@druid.uucp> darcy@druid.UUCP (D'Arcy J.M. Cain) writes: > ... >#include <stdio.h> >int main(int argc, char **argv) >{ > printf("%s has %d arguments\n", *argv, argc); > exit(0); >} > >The compiler will give a warning that a function (main) which should >return an int does not return anything. ... >You now have added code (which won't be optimised out) which has no other >purpose than to shut the compiler up. ... Are you really concerned about one return statement in one function in the entire program taking up code space but never being executed? Do you ever include error-checking code in your programs to catch "impossible" conditions? You expect such code never to be executed, and it surely uses more code space than "return 0;" at the end of main(). >In practice the exit may not even be in the main routine. But what happens if *that* exit doesn't get executed (presumably due to an error), and the program *does* return to main? You should in that case return some error value rather than 0 anyway, so you find out about the incorrect return. -- Steve Clamage, TauMetric Corp, steve@taumet.com
karl@haddock.ima.isc.com (Karl Heuer) (06/05/90)
In article <239@taumet.COM> steve@taumet.UUCP (Stephen Clamage) writes: >In article <1990Jun2.091606.9125@druid.uucp> darcy@druid.UUCP (D'Arcy J.M. Cain) writes: >>int main(int argc, char **argv) { ... exit(0); } >>[complains about int-valued function that seems to return void. But if you >>add a `return 0',] you now have added code (which won't be optimised >>out) which has no other purpose than to shut the compiler up. ... > >Are you really concerned about one return statement in one function in >the entire program taking up code space but never being executed? On the implementation that I normally use, exit() is known to be a dead function. Hence, adding a `return' statement would *create* a warning about unreachable code. Besides which, you can't just write `exit(0); return 0;'. You also have to include a comment that says why you're doing something so silly, lest the next person to read the code think you did it out of ignorance. Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint
steve@taumet.com (Stephen Clamage) (06/05/90)
In article <16790@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: >On the implementation that I normally use, exit() is known to be a dead >function. Hence, adding a `return' statement would *create* a warning about >unreachable code. It seems some compilers complain about return, and some about absence of return. What to do? What to do? >Besides which, you can't just write `exit(0); return 0;'. You also have to >include a comment that says why you're doing something so silly, lest the next >person to read the code think you did it out of ignorance. True enough. You can add a return following the exit, risking warnings from the compiler, or omit it, risking warnings from the compiler. In this particular case, it would seem more sensible to omit the return, since the ANSI standard says that exit cannot return to its caller. With non-ANSI compilers, I have no preference. My major point, however, was the hypothetical program by the orginal poster which is intended to exit from some nested function and never get back to main(). If we for the moment assume this is good programming practice, I claim you still want a "return x;" at the end of main(), with a comment saying this is an error return. -- Steve Clamage, TauMetric Corp, steve@taumet.com
e89hse@rigel.efd.lth.se (06/06/90)
In article <239@taumet.COM>, steve@taumet.COM (Stephen Clamage) writes: >In article <1990Jun2.091606.9125@druid.uucp> darcy@druid.UUCP (D'Arcy J.M. Cain) writes: >> ... >>#include <stdio.h> >>int main(int argc, char **argv) >>{ >> printf("%s has %d arguments\n", *argv, argc); >> exit(0); >>} >> >>The compiler will give a warning that a function (main) which should >>return an int does not return anything. ... >>You now have added code (which won't be optimised out) which has no other >>purpose than to shut the compiler up. ... > >Are you really concerned about one return statement in one function in >the entire program taking up code space but never being executed? But that is ugly. In most unix versions of lint at least you can put: /*NOTREACHED*/ after exit() to mark that the program never get to that point.
karl@haddock.ima.isc.com (Karl Heuer) (06/11/90)
In article <246@taumet.com> steve@taumet.UUCP (Stephen Clamage) writes: >[Given `int main(void) { ... exit(0); }'] It seems some compilers [would >complain if a `return' were added], and some about absence of return [on an >int function]. What to do? What to do? My opinion: leave it out, and if the compiler doesn't provide a way to suppress the warning, then complain to the vendor. Since it is very common to leave main() with exit(), and since this is a defensible programming style, the compiler should allow it--even if it has to make main() a special case. Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint
cknight@polyslo.CalPoly.EDU (King Claudius) (06/11/90)
karl@haddock.ima.isc.com (Karl Heuer) writes: ?steve@taumet.UUCP (Stephen Clamage) writes: ?>[Given `int main(void) { ... exit(0); }'] It seems some compilers [would ?>complain if a `return' were added], and some about absence of return [on an ?>int function]. What to do? What to do? ? ?My opinion: leave it out, and if the compiler doesn't provide a way to ?suppress the warning, then complain to the vendor. Since it is very common to ?leave main() with exit(), and since this is a defensible programming style, ?the compiler should allow it--even if it has to make main() a special case. An easier way to do this is to declare main as returning void... void main (void) {...} -- cknight@polyslo.calpoly.edu ---King Claudius---
thorinn@skinfaxe.diku.dk (Lars Henrik Mathiesen) (06/11/90)
cknight@polyslo.CalPoly.EDU (King Claudius) writes: >An easier way to do this is to declare main as returning void... >void main (void) {...} Yeah, and if a int-declared main expects a space to be left on the stack for its return value, and a void-declared doesn't? Funny core-dump time. The main function has a defined interface to the runtime system, and you deviate from it at your peril. It may not matter in _this_ release of _your_ compiler on _your_ operating system, but ... -- Lars Mathiesen, DIKU, U of Copenhagen, Denmark [uunet!]mcsun!diku!thorinn Institute of Datalogy -- we're scientists, not engineers. thorinn@diku.dk
mcdaniel@amara.uucp (Tim McDaniel) (06/11/90)
cknight@polyslo.CalPoly.EDU (King Claudius) suggests: An easier way to do this is to declare main as returning void... No, you can't. To repeat what was just said a few weeks ago: the ANSI C standard says that main may be defined in one of two ways, in a non-standalone- program environment: int main(void) { /* ... */ } or int main(int argc, char *argv[]) { /* ... */ } (Or, presumably, equivalent formulations.) Section 2.1.2.2.1. -- "I'm not a nerd -- I'm 'socially challenged'." Tim McDaniel Internet: mcdaniel@adi.com UUCP: {uunet,sharkey}!puffer!mcdaniel
karl@haddock.ima.isc.com (Karl Heuer) (06/11/90)
In article <1990Jun11.123122.13249@diku.dk> thorinn@skinfaxe.diku.dk (Lars Henrik Mathiesen) writes: >cknight@polyslo.CalPoly.EDU (King Claudius) writes: >>An easier way to do this is to declare main as returning void... > >[But that could blow up if the function-call interface is different for void >functions.] Also, this practice may provoke a diagnostic from the compiler if it has builtin knowledge of the correct prototype(s) for main(). (I find this scenario more likely than the previous, especially in view of the common missing-semicolon-before-main bug described in the FAQ.) Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint
darcy@druid.uucp (D'Arcy J.M. Cain) (06/12/90)
In article <2672bfbb.6b94@petunia.CalPoly.EDU> cknight@polyslo.CalPoly.EDU (King Claudius) writes: >karl@haddock.ima.isc.com (Karl Heuer) writes: >?My opinion: leave it out, and if the compiler doesn't provide a way to >?suppress the warning, then complain to the vendor. Since it is very common to >?leave main() with exit(), and since this is a defensible programming style, >?the compiler should allow it--even if it has to make main() a special case. >An easier way to do this is to declare main as returning void... > Bringing us back to last week's discussion of declaring main as void. I think Karl had the right idea. No matter how elegant it is to think of it otherwise main is not the same as other functions and a few special rules (in a hosted environment) are not unreasonable. -- D'Arcy J.M. Cain (darcy@druid) | Government: D'Arcy Cain Consulting | Organized crime with an attitude West Hill, Ontario, Canada | (416) 281-6094 |