Reputation: 291
I'm learning C. I have done some little experimentswhen I'm learning some chapters.
The major question is I can't understand why the result of the code's execution is following, because it doesn't meet what I thought code would go.
source code:
#include <stdio.h>
int imax();
int main(void)
{
printf("%zd %zd\n", sizeof(int), sizeof(double));
printf("The maximum of %d and %d is %d.\n", 3, 5, imax(3));
printf("The maximum of %d and %d is %d.\n", 3, 5, imax(3.0, 1000.0));
printf("The maximum of %d and %d is %d.\n", 3, 5, imax(3.0));
printf("The maximum of %d and %d is %d.\n", 3, 5, imax(1000.0));
return 0;
}
int imax(n, m)
int n, m;
{
return (n > m ? n: m);
}
the output:
What I can't understand is why the last three print statements print same words! I know I am do a test for researching what will happen when the declaration of a function using old style which do not care the formal parameters' type. In the context, I design four cases which the calling function's actual arguments do not match with the requirement of the called function's formal parameters.
I know this is relevant to the mechanism of the stack in C. And I try my best to search why. In my opinion, the last three print statements should behave different. In fact, I think the statement imax(3.0, 1000.0) may be same with imax(3.0) or imax(1000.0) but it's impossible be same with both!
Upvotes: 0
Views: 69
Reputation: 1
Your code is not conforming to C99 or C11 standard. Don't use anything older (like K&R C).
This is wrong or at least undefined behaviour and you should be scared of it.
You really should have a prototype (in C99 or C11 style) for every function, that is you need to have a declaration of every used function.
(In old C89 or K&R C, that was not mandatory; but today you should code in C99 at least)
Actually you should code:
#include <stdio.h>
int imax(int, int);
int main(void)
{
printf("%zu %zu\n", sizeof(int), sizeof(double));
// WRONG CODE BELOW: the compiler should reject it or emit warnings.
printf("The maximum of %d and %d is %d.\n", 3, 5, imax(3));
printf("The maximum of %d and %d is %d.\n", 3, 5, imax(3.0, 1000.0));
printf("The maximum of %d and %d is %d.\n", 3, 5, imax(3.0));
printf("The maximum of %d and %d is %d.\n", 3, 5, imax(1000.0));
return 0;
}
int imax(int n, int m)
{
return (n > m ? n: m);
}
and a recent compiler would reject that code. Be sure to compile with all warnings enabled, e.g. gcc -Wall -Wextra -g
)
What really happens (on a mismatch between declared function signature and incorrect call) depends upon the ABI and the calling conventions. Today, on x86-64 with SVR4/Linux ABI, some arguments are passed thru registers. So even if you forced the compiler (e.g. by casting some function address to a function pointer and using that) what would happen is undefined and implementation specific.
If you book shows K&R C code, you need to use a better book showing C99 code (or C11). Bookmark also some C reference site (for C99 at least).
Read the C11 standard, e.g. n1570.
In 2018, you should avoid coding in K&R C (unless forced to).
I know this is relevant to the mechanism of the stack in C.
This is a misconception. Implementations are not required to have a call stack. And most recent implementations don't pass every argument on the stack (most calling conventions may use registers, details are implementation specific).
On Ubuntu, I recommend compiling with gcc -Wall -Wextra -g
-all warnings and debug info-. And probably eliciting the language standard, e.g. by adding -std=c99
or -std=gnu11
. When you want to benchmark, enable more compiler optimizations (e.g. with -O2
)
Upvotes: 2
Reputation: 2506
Edit : To be more precise, it's because you implement your function with the K&R style. Change "int imax(n , m)" to "int imax(int n, int m)" too.
you have to correct the prototype of imax
too because function without anything in the parenthesis allow this kind of thing.
When there is nothing in the parameter of the function, the function can take any number of argument. but this is useless and dangerous, since it can lead to security flaw. It's useless because you can't retrieve the correct amount of argument, and it's a security flaw because you can put any number of argument and this can smash your calling stack.
Just take
int imax();
and transform in
int imax(int n, int m);
Now, you function must take two parameter, and compilation will fail if it's not the case.
If you want a function that have no argument, put void in it to ensure that the function can't called with argument
int funcname(void);
Upvotes: 2
Reputation: 1
int imax();
and
int imax(n, m)
int n, m;
{
return (n > m ? n: m);
}
is an ancient style of C code. Don't use it, as one of it's problems is it doesn't do any function argument checking.
The proper standardized code would be
int imax( int n, int m)
and
int imax( int n, int m)
{
return (n > m ? n: m);
}
Upvotes: 4