Please explain how prog works.

#include<stdio.h> int f(); int main() { f(1); f(1,2); f(1,2,3); } f(int i,int j,int k) { printf("%d %d %d",i,j,k); } 

it works fine (no errors) ... can plz explain how it is executed? how are f (1) and f (1,2) related to f (int, int, int)?

+7
c
source share
6 answers

I should have a different definition of "error" :-) What prints the first two times when you call f ? I get

 1 -1216175936 134513787 1 2 134513787 1 2 3 

for my three function calls.

What you see is deterrence from the earliest days of C, when people played unattended with their function calls.

All that happens is that you call the f function and print three values ​​from the stack (yes, even if you only give one or two). What happens when you are not sure enough that your program will most likely just use what it was in any case, which usually leads to data problems when reading and a catastrophic write failure.

This is completely compiled, although very unreasonable C. And I mean that in a very real “undefined behavior” the meaning of the word (in particular, refers to C99: “If the expression denoting the function to be called is a type that does not include a prototype ,. .. if the number of arguments is not equal to the number of parameters, the behavior is undefined ").

You should really provide fully formed function prototypes, such as:

 void f(int,int,int); 

so that your compiler takes this problem and uses ellipses ( ... ) in variable parameters.


Aside, what usually happens under the covers is that the calling function starts from the stack, like:

 12345678 11111111 

and pushes (for example) two values ​​onto the stack, so that it ends like this:

 12345678 11111111 2 1 

When the called function uses the first three values ​​on the stack (since it wants to), it discovers that it has 1 , 2 and 11111111 .

It does what it needs to do and then returns, and the calling function clears these two values ​​from the stack (this is called a strategy that calls a good call). Woe to everyone who tries to do this with their trustworthy strategy :-) although this is rather unusual in C, as it makes variable argument functions like printf little harder to do.

+14
source share

This announcement:

 int f(); 

... tells the compiler " f is a function that takes some fixed number of arguments and returns int ". Then you try to call it with one, two and three arguments - the C compilers are conceptually single-pass (after preliminary processing), so at the moment the compiler does not have the information available for discussion with you.

Your actual implementation of f() contains three int arguments, so calls that provide only one and two arguments cause undefined behavior - this is an error, which means that the compiler should not give you an error message, and everything can happen when you run the program .

+4
source share
 int f(); 

In C, this declares a function that takes a variable number of arguments, i.e. it is equivalent to the following in C ++

 int f(...); 

To verify this, use int f();

following:
 int f(void); 

This will make the compiler complain.

Please note: the c linker curator is also involved here ... The C-linker does not check the arguments passed to the function at the dial-peer, and simply refers to the first public character with the same name. Thus, the use of f () in main is allowed due to the declaration of int f() . But the linker binds the function f (int, int, int) during the link time on the call sites. Hope this makes sense (please let me know if this is not the case)

+3
source share

It works fine, since int f() means another answer has already said: it means an indefinite number of arguments. This means that you can call it with the number of arguments you want (also more than 3), without the compiler talking about it.

The reason it works "under the cover" is because the arguments are pushed onto the stack and then access the "from" the stack in the f function. If you pass 0 arguments, i, j, k function "matches" the values ​​in the stack, which of the PoV function are garbage. However, you can access their values. If you pass 1 argument, one of the three ijk accesses the value, the others receive garbage. And so on.

Note that the same reasoning works if the arguments are passed in some other way, but in any case this convention is used. Another important aspect of these agreements is that the caller is not responsible for adjusting the stack; it depends on the caller who knows how many arguments are put forward for the real one. If this were not the case, the definition of f might suggest that it should "set up" the stack to "release" three integers, and this could cause some kind of crash.

What you wrote is great for the current standard (on gcc compilations without warnings even with -std=c99 -pedantic , there is a warning there, but this is about the missing int before defining f ), even though many people find this disgusting and call it This is an "obsolete feature." Surely, your use in the sample code does not show any benefit, and probably this can help error traversers to use prototyping more coherently! (But still, I prefer With Ada)

add

A more "useful" use of a "function" that does not cause an "undefined" problem might be

 #include<stdio.h> int f(); int main() { f(1); f(2,2); f(3,2,3); } int f(int i,int j,int k) { if ( i == 1 ) printf("%d\n", i); if ( i == 2 ) printf("%d %d\n", i, j); if ( i == 3 ) printf("%d %d %d\n", i, j, k); } 
+1
source share

When compiling the same program with the g ++ compiler, you see the following errors -

 g++ program.c program.c: In function `int main()': program.c:2: error: too many arguments to function `int f()' program.c:6: error: at this point in file program.c:2: error: too many arguments to function `int f()' program.c:7: error: at this point in file program.c:2: error: too many arguments to function `int f()' program.c:8: error: at this point in file program.c: At global scope: program.c:12: error: ISO C++ forbids declaration of `f' with no type 

Using gcc with the option -std = c99 just gives a warning

Compile the same program with the same standard as g ++ by default, it displays the following message:

 gcc program.c -std=c++98 cc1: warning: command line option "-std=c++98" is valid for C++/ObjC++ but not for C 

Then my answer would be either with the compilers conforming to another standard that is not as restrictive as the one that conforms to C ++.

0
source share

In C, an declaration must declare at least the type of return value. So

 int f(); 

declares a function that returns an int . This expression does not contain any information about the parameters that the function performs. Function Definition

 f(int i,int j,int k) { printf("%d %d %d",i,j,k); } 

It is now known that the function accepts three int s. If you call a function with arguments other than the definition, you will not get a compile-time error, but a run-time error (or if you don't like the negative connotation of the error: "undefined behavior"). The C compiler is not forced by the standard to catch these inconsistencies.

To prevent these errors, you should use the correct function prototypes, such as

 f(int,int,int); //in your case f(void); //if you have no parameters 
0
source share

All Articles