I'm not sure of the correct terminology to use to describe this problem, but I will try my best.
I'm writing a toy program that prints the factorial of 12 and 13 in test.c:
#include <stdio.h>
int main(void)
{
printf("%ld\n", factorial(12));
printf("%ld\n", factorial(13));
return 0;
}
The factorial function is defined in a shared library with source fact.c
long factorial(int n)
{
long r = 1;
while (n > 1) r *= n--;
return r;
}
I am compiling the shared library and my program with the following commands:
$ gcc -shared -fPIC -o libfact.so fact.c
$ gcc -L. -lfact test.c
I am on x86-64, so I expect that factorial(13)
(13! = 6227020800) does not overflow a 64-bit long. However, I get a strange result.
$ LD_LIBRARY_PATH=. ./a.out
479001600
1932053504
Here, 1932053504 happens to be the decimal value of the lower 32 bits of the correct result. If, however, I insert the function prototype long factorial(int)
at the top of test.c and recompile, I get the correct result.
$ LD_LIBRARY_PATH=. ./a.out
479001600
6227020800
This leaves me with a couple questions:
- What is the assumed return type if I do not specify a prototype in test.c? Is this compiler dependent?
- Without a prototype, I seem to be able to pass in any arbitrary number of arguments to
factorial
. Is this related to this question about C void arguments and this question about function prototypes? - Why doesn't the linker throw an undefined reference error?