Author |
Message |
Robert Gilste #1 / 15
|
 stdlib.h
Sorry if this crowds into the non-ANSI territory too much, but I had a question related to some code that I produced using drand48. The question isn't about drand48, but rather the behavior that the code exhibited when I forgot to #include <stdlib.h> If the function call required stdlib to work, why would it work differently when it wasn't included. Code 1: #include <stdio.h> main() { stuff requiring stdlib.h Quote: }
Code 2: #include <stdio.h> #include <stdlib.h> main() { stuff requiring stdlib.h Quote: }
Why would code 1 produce wrong answers? I would expect code 1 to not compile at all or if it compiled to get the right answers. Would that just be a function of the compiler? I'm just kind of curious about what goes on behind the scenes to make the program run partially, rather than not at all or all the way. -- All these opinions are mine, and are not necessarily shared by The Boeing Company.
|
Sat, 28 Aug 2004 23:40:57 GMT |
|
 |
Lew Pitch #2 / 15
|
 stdlib.h
On Tue, 12 Mar 2002 15:40:57 GMT, Robert Gilster Quote:
>Sorry if this crowds into the non-ANSI territory too much, but I had a >question related to some code that I produced using drand48. The >question isn't about drand48, but rather the behavior that the code >exhibited when I forgot to >#include <stdlib.h> >If the function call required stdlib to work, why would it work >differently when it wasn't included.
Ask this: What's in stdlib.h that would change the behaviour of a function? I'll give you a hint: what does atof() return, and why would leaving stdlib out change this? Quote: >Code 1: >#include <stdio.h> >main() >{ > stuff requiring stdlib.h >} >Code 2: >#include <stdio.h> >#include <stdlib.h> >main() >{ > stuff requiring stdlib.h >} >Why would code 1 produce wrong answers? I would expect code 1 to not >compile at all or if it compiled to get the right answers. Would that >just be a function of the compiler? I'm just kind of curious about what >goes on behind the scenes to make the program run partially, rather than >not at all or all the way.
Well, another (double) hint then: what do function prototypes do, and what functions are prototyped in stdlib.h? Lew Pitcher, Information Technology Consultant, Toronto Dominion Bank Financial Group
(Opinions expressed are my own, not my employer's.)
|
Sun, 29 Aug 2004 00:55:59 GMT |
|
 |
Gergo Baran #3 / 15
|
 stdlib.h
Quote:
> Sorry if this crowds into the non-ANSI territory too much, but I had a > question related to some code that I produced using drand48. The > question isn't about drand48, but rather the behavior that the code > exhibited when I forgot to > #include <stdlib.h> > If the function call required stdlib to work, why would it work > differently when it wasn't included.
The prototype of drand48 is double drand48(void); (at least that's what my man pages say; it doesn't really matter except for the fact that it does not return int). In "traditional" K&R C, and for backwards compatibility in C89 as well, it was allowed to call functions which had not been declared. The compilers acted as if the function had been declared with a return type of int an a fixed but unknown number of parameters. That is, if you called a function called drand48 but had not declared it beforehand, the compiler implicitly inserted the declaration int drand48(); before the call. Calling such a function is fine as long as the call agrees with the function's definition; but if they don't agree, the behavior is undefined. In your case, the function definition in the C library returns a double, but the calling code tries to retrieve that return value as if it were an int; chaos ensues. Unless you need to be backward compatible to age-old C compilers, it's best to prototype all functions before you call them. If the functions are from a library, #including the correct header is supposed to take care of this. Gergo -- "... we define the quality factor Q_p as the ratio of the resistance to the reactance of the inductance at resonance." -- Allan R. Hambley, "Electrical Engineering: Principles and Applications"
|
Sun, 29 Aug 2004 00:58:51 GMT |
|
 |
Robert Gilste #4 / 15
|
 stdlib.h
Quote:
> > Sorry if this crowds into the non-ANSI territory too much, but I had a > > question related to some code that I produced using drand48. The > > question isn't about drand48, but rather the behavior that the code > > exhibited when I forgot to > > #include <stdlib.h> > > If the function call required stdlib to work, why would it work > > differently when it wasn't included. > The prototype of drand48 is > double drand48(void); > (at least that's what my man pages say; it doesn't really matter > except for the fact that it does not return int). > In "traditional" K&R C, and for backwards compatibility in C89 as > well, it was allowed to call functions which had not been declared. > The compilers acted as if the function had been declared with a > return type of int an a fixed but unknown number of parameters. That > is, if you called a function called drand48 but had not declared it > beforehand, the compiler implicitly inserted the declaration > int drand48(); > before the call. > Calling such a function is fine as long as the call agrees with the > function's definition; but if they don't agree, the behavior is > undefined. In your case, the function definition in the C library > returns a double, but the calling code tries to retrieve that return > value as if it were an int; chaos ensues. > Unless you need to be backward compatible to age-old C compilers, > it's best to prototype all functions before you call them. If the > functions are from a library, #including the correct header is > supposed to take care of this. > Gergo
Got it thanks. It surprised me that the compiler would even know what drand48 was in the first place, since I figured it would be located somewhere, where stdlib referenced it. But I think I understand what you mean, pay attention to the proper header files and remember to prototype - otherwise you get an int. -- All these opinions are mine, and are not necessarily shared by The Boeing Company.
|
Sun, 29 Aug 2004 02:02:17 GMT |
|
 |
Ryan Henness #5 / 15
|
 stdlib.h
Quote:
> If the function call required stdlib to work, why would it work > differently when it wasn't included. > Code 1: > #include <stdio.h> > main() > { > stuff requiring stdlib.h > } > Code 2: > #include <stdio.h> > #include <stdlib.h> > main() > { > stuff requiring stdlib.h > } > Why would code 1 produce wrong answers? I would expect code 1 to not > compile at all or if it compiled to get the right answers. Would that > just be a function of the compiler? I'm just kind of curious about what > goes on behind the scenes to make the program run partially, rather than > not at all or all the way.
This is a side-effect of implicit function declaration and implicit int return value of said functions. Proper header files, such as the standard library headers, only contain declarations for functions and user-defined data types (and #defines etc). The point is that the header file doesn't actually import any code into your program when you include it. That is the job of the linker. The explanation that I'm about to give doesn't apply to C99 impelementations; my draft of the standard says the features were removed in its Foreward. So, you tell your compiler to compile the file marked "Code 1". It goes down, line by line, until it hits a call to an unrecognized function (drand48 in your case). The compiler then says to itself "have I seen a declaration for this function?". The answer is no. This part's important: the language specifies that a function used without a prior declaration in scope is given an *implicit declaration* of "int func();". This means the function is declared to return an int and take some unspecified number of parameters. So at this point, the compiler is happy. It has a function call, it has a declaration for that function, and everything's grand. It proceeds to compile the rest of your file into an object file, leaving stubs for the functions whose definitions aren't yet known, so that they can be linked in later. Now we get to the kicker. The linker, without you telling it to do so, will link in parts of the standard library for you, including the code that is partnered with stdlib.h. We know your compiler is happy; your linker is happy too, as it was able to find an object file using drand48() *and* an object file that contains the definition for drand48(). Boom, it links you a pretty executable. Now you try to use your program. In main, you call drand48(), and the machine code is set up to expect an integer. Unfortunately, drand48() returns something that's (probably) wider than an int. The return will be interpreted as though it was an int, and whatever happens, happens. If the actual return was some kind of non-integral value, such as a pointer, what happens is likely to be "bad". There you have it. Note that if try to use a function that actually *does* return an int, everything will work out just fine. The program: /* NO #include <stdio.h> */ int main(void) { puts("Hello World!"); return 0; Quote: }
Is EXACTLY the same as the program /* NO #include <stdio.h> /* forward declaration for puts*/ int puts(); int main(void) { puts("Hello World!"); return 0; Quote: }
Both will compile just fine, and if your linker can find the definition for puts() somewhere, you're golden. Both will work properly, as though you had included stdio.h. *Question for the real experts*: Is it by pure luck that the linker will automatically link in the stuff in <std*.h>, or is that behaviour specified somewhere? Hope this helps, Ryan.
|
Sun, 29 Aug 2004 02:43:01 GMT |
|
 |
Robert Gilste #6 / 15
|
 stdlib.h
Quote:
> > If the function call required stdlib to work, why would it work > > differently when it wasn't included.
<MAJOR SNIPPAGE> Quote: > This is a side-effect of implicit function declaration and implicit int > return value of said functions.
<Snip of great explanation> Quote: > Hope this helps, > Ryan.
Sorry for being so vulgar here, but that's gay! You have to include it, but only so the compiler doesn't hose it up. I suppose the best solution would be for the programmer to have diligence and check his/her code for error before compiling - but hey, if I can't remember to include <stdlib.h> how can you expect me to debug my own 4 line program?!! I guess that proves the notion that a computer is only as smart as the programmer behind it. I appreciate the clarification, it makes sense to me and explains what I see - although I'm with you on finding out why stdlib still inserts itself into the code even when not called. -- All these opinions are mine, and are not necessarily shared by The Boeing Company.
|
Sun, 29 Aug 2004 03:53:18 GMT |
|
 |
Tobias Oe #7 / 15
|
 stdlib.h
Quote:
> Sorry if this crowds into the non-ANSI territory too much, but I had a > question related to some code that I produced using drand48. The > question isn't about drand48, but rather the behavior that the code > exhibited when I forgot to > #include <stdlib.h> > If the function call required stdlib to work, why would it work > differently when it wasn't included. > Code 1: > #include <stdio.h> > main() > { > stuff requiring stdlib.h > } > Code 2: > #include <stdio.h> > #include <stdlib.h> > main() > { > stuff requiring stdlib.h > } > Why would code 1 produce wrong answers? I would expect code 1 to not > compile at all or if it compiled to get the right answers. Would that > just be a function of the compiler? I'm just kind of curious about what > goes on behind the scenes to make the program run partially, rather than > not at all or all the way.
If you don't include stdlib, all functions of it that you use will be declared to return int and take arguments of the type provided at the first call the compiler encounters. So if you have char *x=malloc(10); The compiler will think that the prototype of malloc is int malloc(int) and do the 'apropriate' promotions. In the new C99 standard you can't call a function that has no prototype in scope just to avoid this kind of confusion. Tobias.
|
Sun, 29 Aug 2004 04:18:23 GMT |
|
 |
Kevin Lacquemen #8 / 15
|
 stdlib.h
[...] RH> *Question for the real experts*: RH> Is it by pure luck that the linker will automatically link in the stuff RH> in <std*.h>, or is that RH> behaviour specified somewhere? If the linking stage doesn't include these functions, it is not a conforming hosted implementation. For example, gcc without the -lm option is not conforming, as it doesn't include the <math.h> functions. Many (most?) compilers for hosted implementations include most of the standard library automagically when linking. Many (most?) compilers for freestanding implementations do not link the standard library. RH> Hope this helps, RH> Ryan. Hope this answers your question. Cheers, Kevin -- He that breaks a thing to find out what it is has left the path of wisdom -- Gandalf the Grey
|
Sun, 29 Aug 2004 16:52:07 GMT |
|
 |
Finny Merri #9 / 15
|
 stdlib.h
On Tue, 12 Mar 2002 19:53:18 GMT, Robert Gilster Quote:
>Sorry for being so vulgar here, but that's gay! You have to include it,
^^^ I don't mind you being vulgar, but that's offensive. Please don't be a narrow-minded redneck around here, KTHX. Quote: >but only so the compiler doesn't hose it up. I suppose the best >solution would be for the programmer to have diligence and check his/her >code for error before compiling - but hey, if I can't remember to >include <stdlib.h> how can you expect me to debug my own 4 line >program?!!
Did you try -Wall? Quote: >I guess that proves the notion that a computer is only as smart as the >programmer behind it.
GIGO Quote: >I appreciate the clarification, it makes sense to me and explains what I >see - although I'm with you on finding out why stdlib still inserts >itself into the code even when not called.
So you can do things like: int printf(const char * restrict _fmt, ...) int main(void) { printf("Hello, world!\n"); Quote: }
-- "Pedants make the best programmers" - Richard Heathfield Indent-o-meter 01234567 ^
|
Mon, 30 Aug 2004 05:02:18 GMT |
|
 |
Steve Gravro #10 / 15
|
 stdlib.h
Quote:
>[...] > RH> *Question for the real experts*: > RH> Is it by pure luck that the linker will automatically link in the stuff > RH> in <std*.h>, or is that > RH> behaviour specified somewhere? >If the linking stage doesn't include these functions, it is not a >conforming hosted implementation. For example, gcc without the -lm >option is not conforming, as it doesn't include the <math.h> >functions.
Is the implementation really required to link the entire standard library, or only the portions that are used? For instance, suppose I have a linker which is capable of linking or excluding individual objects. Such a linker could include only the parts of the standard library which are referenced (either directly or indirectly) and any conforming program would still behave as required by the standard. I don't know what the standard has to say, but I would be hard-pressed to find reason to deem such an implementation non-conforming. -- Never make a sweeping statement in comp.lang.c (except when...). --Richard Heathfield in comp.lang.c
|
Mon, 30 Aug 2004 10:49:02 GMT |
|
 |
Kevin Lacquemen #11 / 15
|
 stdlib.h
[...] SG> Is the implementation really required to link the entire standard library, SG> or only the portions that are used? For instance, suppose I have a linker SG> which is capable of linking or excluding individual objects. Such a linker SG> could include only the parts of the standard library which are referenced SG> (either directly or indirectly) and any conforming program would still SG> behave as required by the standard. No, the implementation is only required to link the portions of the library that are used. However, it must be able to link the entire library. Even if I don't use printf(), for example, the library must be _able_ to link printf(). [...] Cheers, Kevin -- He that breaks a thing to find out what it is has left the path of wisdom -- Gandalf the Grey
|
Mon, 30 Aug 2004 14:46:42 GMT |
|
 |
Dan P #12 / 15
|
 stdlib.h
Quote:
>>[...] >> RH> *Question for the real experts*: >> RH> Is it by pure luck that the linker will automatically link in the stuff >> RH> in <std*.h>, or is that >> RH> behaviour specified somewhere? >>If the linking stage doesn't include these functions, it is not a >>conforming hosted implementation. For example, gcc without the -lm >>option is not conforming, as it doesn't include the <math.h> >>functions.
This depends on the system's libraries, which have nothing to do with gcc. Quote: >Is the implementation really required to link the entire standard library, >or only the portions that are used?
It depends on what you mean by "link the entire standard library". If you mean "scan the entire standard library for the functions needed by the program", the answer is yes. If you mean "include the definitions of all the standard functions in the generated executable image, whether they are used by the program or not", the answer is no. Dan -- Dan Pop DESY Zeuthen, RZ group
|
Mon, 30 Aug 2004 22:09:02 GMT |
|
 |
Billy Chamble #13 / 15
|
 stdlib.h
Quote:
> On Tue, 12 Mar 2002 19:53:18 GMT, Robert Gilster
> >Sorry for being so vulgar here, but that's gay! You have to include it,
^^^ Quote: > I don't mind you being vulgar, but that's offensive. Please don't be > a narrow-minded redneck around here, KTHX.
Please don't stereotype all rednecks as narrow-minded. Thanks.
|
Mon, 30 Aug 2004 22:59:41 GMT |
|
 |
Jirka Klau #14 / 15
|
 stdlib.h
Quote:
>>On Tue, 12 Mar 2002 19:53:18 GMT, Robert Gilster
>>>Sorry for being so vulgar here, but that's gay! You have to include it, > ^^^ >>I don't mind you being vulgar, but that's offensive. Please don't be >>a narrow-minded redneck around here, KTHX. > Please don't stereotype all rednecks as narrow-minded.
He didn't. He explicitly said *narrow-minded* redneck. ;-) Jirka
|
Mon, 30 Aug 2004 23:08:03 GMT |
|
 |
Stig Brautase #15 / 15
|
 stdlib.h
Quote:
>>I appreciate the clarification, it makes sense to me and explains what >>I see - although I'm with you on finding out why stdlib still inserts >>itself into the code even when not called. > So you can do things like: > int printf(const char * restrict _fmt, ...)
^ missing ";" here ---/ hey, just trying to live up to your .sig :) Quote: > int main(void) > { > printf("Hello, world!\n"); > }
Stig -- brautaset.org
|
Tue, 31 Aug 2004 05:30:07 GMT |
|
|
|