Implicit Declaration
Table of Contents
1. Implicit Declaration
1.1. The problem
/* main.c */ #include <stdint.h> #include <stdio.h> /* int64_t foo(); */ int main(int argc, char *argv[]) { int64_t x = foo(); printf("after return: %ld\n", x); return 0; } /* ----------------------------------------------- */ /* foo.c */ #include <stdint.h> #include <stdio.h int64_t foo() { int64_t ret = 1l << 31; printf("before return: %ld\n", ret); return ret; }
$> gcc main.c foo.c main.c: In function ‘main’: main.c:6:17: warning: implicit declaration of function ‘foo’ [-Wimplicit-function-declaration] int64_t x = foo(); $> ./a.out before return: 2147483648 after return: -2147483648
but if we add the declaration `int64_t foo();` in main.c
$> gcc main.c foo.c $> ./a.out before return: 2147483648 after return: 2147483648
1.2. Analysis
Did you notice the warning `implicit description of function ‘foo’ [-Wimplicit-function-declaration]`
When C doesn't find a declaration, it assumes this implicit declaration: `int f();`, which means the function can receive whatever you give it, and returns an int
What happends in the problematic example:
- when foo returns, it will place 1l<<31, or 0x0000000080000000 in x0 (suppose under aarch64), which is a 64bit register.
- now control returns back to main, the implicit declaration makes `main` believe that `foo` will return an int, so it will fetch the `int` value from w0 (the bottom half of x0), which is 0x80000000.
- then the int value 0x80000000 is cast to int64_t, which will be 0xffffffff80000000 (guess you know why 0xffffffff80000000 instead of 0x0000000080000000)
1.3. 参数
C99 6.5.2.2/6 "Function calls":
If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double.
对于函数参数:
- 整数类型会转换为 int
- 浮点类型会转换为 double