![]() |
invoke function without declaration
Dear all
Once again I come across some question about linking. In f1.c, I have the following function definition. ----------------f1.c------------ #include <stdio.h> void my_print(float a, int b) { printf("%f\t%d\n", a, b); } int add(int a, int b) { return a + b; } In main.c, I call the two function without declaration. ----------------main.c------------- int main(void) { int a = add(1, 2); printf("%d\n", a); my_print(2.0, a); return 0; } Notice here, in file main.c, I don't include any headers, say, 'f1.h', 'stdio.h', and don't declare anything deliberately, trying to get what the result would like to be. In my machine, with compiler gcc on ubuntu, I got some warnings while compiling the code, and the binary file runs happily, printing the following lines: 3 0.000000 1073741824 From the result, I got that 1. the function 'add' and the standard library function 'printf' performs well, because the first line printed is 3. 2. the function 'my_print' doesn't work, the printed line obviously shows. All three function are defined external without declaration in file main.c. But why the first two works well, but the last one fails? Is it undefined in ISO C? Thanks in advance. |
Re: invoke function without declaration
On 11/15/2011 10:20 AM, Stanley Rice wrote:
> Dear all > > Once again I come across some question about linking. In f1.c, I have > the following function definition. > ----------------f1.c------------ > #include <stdio.h> > void my_print(float a, int b) > { > printf("%f\t%d\n", a, b); > } > > int add(int a, int b) > { > return a + b; > } > > In main.c, I call the two function without declaration. > ----------------main.c------------- > int main(void) > { > int a = add(1, 2); > printf("%d\n", a); > my_print(2.0, a); > > return 0; > } > > Notice here, in file main.c, I don't include any headers, say, 'f1.h', > 'stdio.h', and don't declare anything deliberately, trying to get what > the result would like to be. > > In my machine, with compiler gcc on ubuntu, I got some warnings while > compiling the code, and the binary file runs happily, printing the > following lines: > 3 > 0.000000 1073741824 > > From the result, I got that > 1. the function 'add' and the standard library function 'printf' > performs well, because the first line printed is 3. > 2. the function 'my_print' doesn't work, the printed line obviously > shows. > > All three function are defined external without declaration in file > main.c. But why the first two works well, but the last one fails? Is > it undefined in ISO C? > > Thanks in advance. when C does not know the exact type of arguments/return values it assumes 'int'. as long as arguments are in fact ints, it works. by when they differ, problems arise, since compiler put different types on stack, and tries to take different inside the function. it gets even funnier when architecture changes. your code gives different results on ia32 and amd64. real life situation - about a week ago a friend of mine found similar bug in code he develops. for some reason it crashed on amd64, while working stable on ia32. some debugging shown that stdlib.h was not included, thus malloc was not defined, thus compiler assumed it returns 'int' instead of 'void*'. it worked well on ia32, since there, on GCC sizeof(int)==sizeof(void*). on the amd64 however sizeof(int)<sizeof(void*) and program used some random memory space, instead of newly allocated block. notice that similar problems may arise if you do not include some header (say: aaa.h), that you use calls from, but other header you do include (say bbb.h) does that (i.e. bbb.h includes aaa.h). it will work on your machine, but when moved to different implementation of library with bbb.h file, this implicit include may not take place (i.e. bbb.h may DON'T include aaa.h), users of that system will have, possibly nontrivial, problems with your code... summary is short. do NOT never, ever use functions that were not declared. also always include headers of the functions that you use, even if you "know" they are already included by some other header. -- pozdrawiam serdecznie / best regards, Bartek 'BaSz' Szurgot http://www.baszerr.org |
Re: invoke function without declaration
On Nov 15, 6:10*pm, bartek szurgot <no...@m.plz> wrote:
> On 11/15/2011 10:20 AM, Stanley Rice wrote: > > > > > > > > > > > Dear all > > > Once again I come across some question about linking. In f1.c, I have > > the following function definition. > > ----------------f1.c------------ > > #include <stdio.h> > > void my_print(float a, int b) > > { > > * * printf("%f\t%d\n", a, b); > > } > > > int add(int a, int b) > > { > > * * return a + b; > > } > > > In main.c, I call the two function without declaration. > > ----------------main.c------------- > > int main(void) > > { > > * * int a = add(1, 2); > > * * printf("%d\n", a); > > * * my_print(2.0, a); > > > * * return 0; > > } > > > Notice here, in file main.c, I don't include any headers, say, 'f1.h', > > 'stdio.h', and don't declare anything deliberately, trying to get what > > the result would like to be. > > > In my machine, with compiler gcc on ubuntu, I got some warnings while > > compiling the code, and the binary file runs happily, printing the > > following lines: > > 3 > > 0.000000 * *1073741824 > > > From the result, I got that > > 1. the function 'add' and the standard library function 'printf' > > performs well, because the first line printed is 3. > > 2. the function 'my_print' doesn't work, the printed line obviously > > shows. > > > All three function are defined external without declaration in file > > main.c. But why the first two works well, but the last one fails? Is > > it undefined in ISO C? > > > Thanks in advance. > > when C does not know the exact type of arguments/return values it > assumes 'int'. as long as arguments are in fact ints, it works. by when > they differ, problems arise, since compiler put different types on > stack, and tries to take different inside the function. > > it gets even funnier when architecture changes. your code gives > different results on ia32 and amd64. > > real life situation - about a week ago a friend of mine found similar > bug in code he develops. for some reason it crashed on amd64, while > working stable on ia32. some debugging shown that stdlib.h was not > included, thus malloc was not defined, thus compiler assumed it returns > 'int' instead of 'void*'. it worked well on ia32, since there, on GCC > sizeof(int)==sizeof(void*). on the amd64 however > sizeof(int)<sizeof(void*) and program used some random memory space, > instead of newly allocated block. > > notice that similar problems may arise if you do not include some header > (say: aaa.h), that you use calls from, but other header you do include > (say bbb.h) does that (i.e. bbb.h includes aaa.h). it will work on your > machine, but when moved to different implementation of library with > bbb.h file, this implicit include may not take place (i.e. bbb.h may > DON'T include aaa.h), users of that system will have, possibly > nontrivial, problems with your code... > > summary is short. do NOT never, ever use functions that were not > declared. also always include headers of the functions that you use, > even if you "know" they are already included by some other header. > > -- > pozdrawiam serdecznie / best regards, > Bartek 'BaSz' Szurgot > > http://www.baszerr.org I found a similar question in comp.lang.c FAQ list.Qustion 1.25 Functions which are called without a declaration in scope, perhaps because the first call precedes the function's definition, are assumed to be declared as if by: extern int f(); That is, an undeclared function is assumed to return int, and to accept an unspecified number of arguments (though there must be a fixed number of them and none may be ``narrow''). The statement above is not consistant with what you said, 'when C does not know the exact type of arguments/return values it assumes 'int'. as long as arguments are in fact ints, ' The points is that what on earth the type of argument in the function which is not declared is, int or not specified at all? As you can see that even I pass an int variable to the function that requires an int type, the result is confusing. Does the standard say something about this, I got a draft, but don't know where to get the point. |
Re: invoke function without declaration
Stanley Rice <heconghui@gmail.com> writes:
<snip> >> On 11/15/2011 10:20 AM, Stanley Rice wrote: <snip> >> > ----------------f1.c------------ >> > #include <stdio.h> >> > void my_print(float a, int b) >> > { >> > Â* Â* printf("%f\t%d\n", a, b); >> > } >> >> > int add(int a, int b) >> > { >> > Â* Â* return a + b; >> > } >> >> > In main.c, I call the two function without declaration. >> > ----------------main.c------------- >> > int main(void) >> > { >> > Â* Â* int a = add(1, 2); >> > Â* Â* printf("%d\n", a); >> > Â* Â* my_print(2.0, a); >> >> > Â* Â* return 0; >> > } <snip> > I found a similar question in comp.lang.c FAQ list.Qustion 1.25 > > Functions which are called without a declaration in scope, perhaps > because the first call precedes the function's definition, are assumed > to be declared as if by: > > extern int f(); > That is, an undeclared function is assumed to return int, and to > accept an unspecified number of arguments (though there must be a > fixed number of them and none may be ``narrow''). <snip> > Does the standard say something about this, I got a draft, but > don't know where to get the point. Most of what you want is in 6.5.2.2 paragraph 6. I don't think it's productive to try to find out about these sorts of rules by trying things out. It's very easy to think that, because something works, it's valid C. For example, if you'd left out my_print you might have concluded that the program is correct when, in fact, calling a variadic function (like printf) without a prototype in scope is undefined. -- Ben. |
Re: invoke function without declaration
Stanley Rice <heconghui@gmail.com> writes:
[...] > I found a similar question in comp.lang.c FAQ list.Qustion 1.25 > > Functions which are called without a declaration in scope, perhaps > because the first call precedes the function's definition, are assumed > to be declared as if by: > > extern int f(); > That is, an undeclared function is assumed to return int, and to > accept an unspecified number of arguments (though there must be a > fixed number of them and none may be ``narrow''). [...] That's no longer the case in C99. In C99, a call to an undeclared function is a constraint violation. (It's a bad idea in either version of the language.) -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
Re: invoke function without declaration
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
<snip> > Most of what you want is in 6.5.2.2 paragraph 6. And, I have been reminded, paragraph 1 as well. <snip> -- Ben. |
Re: invoke function without declaration
On 11/15/2011 04:20 AM, Stanley Rice wrote:
> Dear all > > Once again I come across some question about linking. In f1.c, I have > the following function definition. > ----------------f1.c------------ > #include <stdio.h> > void my_print(float a, int b) > { > printf("%f\t%d\n", a, b); > } > > int add(int a, int b) > { > return a + b; > } > > In main.c, I call the two function without declaration. > ----------------main.c------------- > int main(void) > { > int a = add(1, 2); > printf("%d\n", a); > my_print(2.0, a); > > return 0; > } > > Notice here, in file main.c, I don't include any headers, say, 'f1.h', > 'stdio.h', and don't declare anything deliberately, trying to get what > the result would like to be. main.c relies upon the implicit int rules from C90. They cause add() to, in effect, be implicitly declared as taking two arguments of type 'int' and returning an int. They cause printf() in main.c to be treated as if took a char* and an int as arguments, and returns an int. They cause my_print() to be treated as if it took a double and an int as arguments, and returns an int. These implicit declarations are correct for add(), but not for printf() or my_print(). As a result, the behavior of your program is undefined. The implementation is not required to issue a diagnostic for such code. Since the problem occurs due to a mismatch between the implicit declaration in one translation unit, and the actual definition in another translation unit, the compiler cannot detect this mismatch. The linker could have enough information to detect it, but it doesn't need that information in order to do it's job, and therefore doesn't necessarily have access to such information. > In my machine, with compiler gcc on ubuntu, I got some warnings while > compiling the code, Good. However, it would have been better to compile in C99 mode, where the implicit int rule has been dropped. Your program provides a prime example of why it was dropped. At least one diagnostic message for this code due to missing declarations is mandatory in C99, and gcc would almost certainly refuse to continue after issuing that message. and the binary file runs happily, printing the > following lines: > 3 > 0.000000 1073741824 > > From the result, I got that > 1. the function 'add' and the standard library function 'printf' > performs well, because the first line printed is 3. The printf() call in main() has undefined behavior; that it appeared to work is a coincidence; it didn't have to work. And even though it appeared to work, it might have malfunctioned in some way that caused something else to go wrong. > 2. the function 'my_print' doesn't work, the printed line obviously > shows. It may seem obvious, but it's wrong. The function my_print() should work perfectly, if called correctly, and if stdout is writeable; it's the call to my_print() inside main() which is defective, not my_print() itself. > All three function are defined external without declaration in file > main.c. But why the first two works well, but the last one fails? Is > it undefined in ISO C? Yes. -- James Kuyper |
Re: invoke function without declaration
Stanley Rice <heconghui@gmail.com> wrote:
> Dear all > > Once again I come across some question about linking. In f1.c, I have > the following function definition. > ----------------f1.c------------ > #include <stdio.h> > void my_print(float a, int b) > { > printf("%f\t%d\n", a, b); > } > > int add(int a, int b) > { > return a + b; > } > > In main.c, I call the two function without declaration. > ----------------main.c------------- > int main(void) > { > int a = add(1, 2); > printf("%d\n", a); > my_print(2.0, a); > > return 0; > } > Implicit declarations are a constraint violation in C99 but valid in C90. In C90, my_print(2.0, a) implicitly returns int, and has to take two arguments: The first is of type double (float is promoted to double) while the second is of type int. Since the prototype of my_print doesn't match, the behavior is undefined, even in C90. -- André Gillibert |
Re: invoke function without declaration
James Kuyper <jameskuyper@verizon.net> writes:
[...] > Good. However, it would have been better to compile in C99 mode, where > the implicit int rule has been dropped. Your program provides a prime > example of why it was dropped. At least one diagnostic message for this > code due to missing declarations is mandatory in C99, and gcc would > almost certainly refuse to continue after issuing that message. Almost, but not quite. gcc's diagnostic for a call to an undeclared function, even with "-std=c99 -pedantic", is merely a warning; after printing the warning, it proceeds under C90 rules. You can make it a fatal error by specifying "-pedantic-errors". This is conforming, of course; the standard doesn't distinguish between fatal errors and non-fatal warnings; it only requires diagnostics. [...] -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
Re: invoke function without declaration
Acid Washed China Blue Jeans <chine.bleu@yahoo.com> writes:
> In article <2727a73c-d008-4dcb-a25d-dce02f665ea7@i6g2000prm.googlegroups.com>, > Stanley Rice <heconghui@gmail.com> wrote: > >> #include <stdio.h> >> void my_print(float a, int b) >> { >> printf("%f\t%d\n", a, b); >> } > >> All three function are defined external without declaration in file >> main.c. But why the first two works well, but the last one fails? Is >> it undefined in ISO C? > > If you don't declare a function f, it is assumed to be > int f() > which passes all arguments with var-args rules. Not exactly, if by "var-args rules" you mean as if calling a variadic function (one with ", ..." in its declaration). Under C90 rules, the implicit declaration is for a function that returns int with a fixed number of parameters corresponding to the promoted types of the actual arguments in the call. So for my_print(2.0, a); the implicit declaration is int my_print(double, int); *not* int my_print(...); (which isn't even a valid declaration; variadic functions must have at least one non-variadic parameter). > So every float argument is promoted to double. However your function expects a > float which on most machines is passed in different manner and binary format. > Much confusion will occur. Right. -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
| All times are GMT. The time now is 09:02 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.