C/GCC环境下函数声明差异为何导致参数类型转换输出结果不同
输出差异的技术原因
该现象由C语言的「无原型函数声明规则」和「默认实参提升机制」共同导致,具体逻辑如下:
- 当
main内的声明写为void foo();时,属于无参数原型的函数声明:- C标准规定这类声明不会告知编译器函数的入参类型,编译器不会做参数类型匹配转换,只会对传入的参数执行默认实参提升:
char类型会被提升为int类型,float类型会被提升为double类型。 - 此时传入的
char c = 60会被提升为4字节(常规32位环境下)的int类型值60,按调用约定传递给foo。 - 但
foo的实际定义是接收8字节的double类型参数,函数执行时会从传参位置读取8个字节解析为浮点数:前4字节是int 60的二进制,后4字节是栈上的未初始化垃圾值,组合后解析出的double值极接近0,所以输出0.0000。
- C标准规定这类声明不会告知编译器函数的入参类型,编译器不会做参数类型匹配转换,只会对传入的参数执行默认实参提升:
- 当声明修改为
void foo(double);时,属于带参数原型的函数声明:- 编译器明确知道
foo需要接收double类型参数,会自动把传入的char类型60隐式转换为double类型的60.0传递,foo读取到的是合法的60.0值,所以输出60.00。
- 编译器明确知道
补充说明:无参数原型的函数声明是C89遗留的过时特性,C99及后续标准已废弃该用法,GCC开启
-Wall -Wstrict-prototypes编译选项时会输出对应警告,生产环境建议所有函数都声明完整的参数原型。
内容的提问来源于stack exchange,提问作者along
相关产品推荐
相关产品推荐

