C语言函数调用中void指针自动转double指针的底层实现疑问
C语言函数调用中指针类型转换的底层运行机制解析
你的代码及运行结果
#include <stdio.h> void foo(double *number) { printf("%f\n", *number); } void bar(void *number) { double *new_number = (double *)number; printf("%f\n", *new_number); } int main() { double test_number = 3.0; double *test_double_pointer = &test_number; void *test_void_pointer = (void *)test_double_pointer; foo(test_double_pointer); foo(test_void_pointer); bar(test_double_pointer); bar(test_void_pointer); return 0; }
运行结果:
3.000000 3.000000 3.000000 3.000000
编译器对各函数调用的处理逻辑
核心要明确:C语言中所有指针的本质都是存储内存地址的数值,同一系统下不同类型指针的内存占用大小一致,区别仅在于编译器对指针解引用时的类型解析规则。下面逐个分析四个调用:
foo(test_double_pointer)- 实参
test_double_pointer是double*类型,和foo的形参类型完全匹配。编译器直接将该指针存储的test_number地址传递给foo的number形参。 foo中解引用number时,编译器按double类型解析地址指向的内存,取出8字节的double数值3.0,通过printf("%f")正常输出。
- 实参
foo(test_void_pointer)- 实参
test_void_pointer是void*类型,C语言允许void*隐式转换为任意对象指针类型(此处为double*)。编译阶段编译器自动完成转换,传递给foo的地址值和test_void_pointer存储的地址完全一致(即test_number的地址)。 - 后续解引用和输出逻辑与第一个调用完全相同,因此得到正确结果。
- 实参
bar(test_double_pointer)- 实参
test_double_pointer是double*类型,C语言允许任意对象指针隐式转换为void*。编译器直接将test_double_pointer存储的地址传递给bar的number形参(void*仅作为无类型地址容器,不会改变地址值)。 bar中显式将void*转回double*,地址仍指向test_number,解引用后取出正确的double值输出。
- 实参
bar(test_void_pointer)- 实参
test_void_pointer是void*类型,和bar的形参类型完全匹配。编译器直接传递地址值,后续转回double*并解引用的逻辑与第三个调用一致,输出正确结果。
- 实参
关键总结
只要转换前后的指针实际指向的内存类型一致(此处均为double),这种指针类型转换在底层不会改变地址值,仅改变编译器对指针指向内存的解析规则,因此所有调用都能正确取出并输出目标值。若指针转换后指向的内存类型不匹配,解引用会触发未定义行为(比如将指向int的void*转成double*后解引用)。
内容的提问来源于stack exchange,提问作者Bomel
相关产品推荐
相关产品推荐

