You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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语言中所有指针的本质都是存储内存地址的数值,同一系统下不同类型指针的内存占用大小一致,区别仅在于编译器对指针解引用时的类型解析规则。下面逐个分析四个调用:

  1. foo(test_double_pointer)

    • 实参test_double_pointer是double*类型,和foo的形参类型完全匹配。编译器直接将该指针存储的test_number地址传递给foo的number形参。
    • foo中解引用number时,编译器按double类型解析地址指向的内存,取出8字节的double数值3.0,通过printf("%f")正常输出。
  2. foo(test_void_pointer)

    • 实参test_void_pointer是void*类型,C语言允许void*隐式转换为任意对象指针类型(此处为double*)。编译阶段编译器自动完成转换,传递给foo的地址值和test_void_pointer存储的地址完全一致(即test_number的地址)。
    • 后续解引用和输出逻辑与第一个调用完全相同,因此得到正确结果。
  3. bar(test_double_pointer)

    • 实参test_double_pointer是double*类型,C语言允许任意对象指针隐式转换为void*。编译器直接将test_double_pointer存储的地址传递给bar的number形参(void*仅作为无类型地址容器,不会改变地址值)。
    • bar中显式将void*转回double*,地址仍指向test_number,解引用后取出正确的double值输出。
  4. bar(test_void_pointer)

    • 实参test_void_pointer是void*类型,和bar的形参类型完全匹配。编译器直接传递地址值,后续转回double*并解引用的逻辑与第三个调用一致,输出正确结果。

关键总结

只要转换前后的指针实际指向的内存类型一致(此处均为double),这种指针类型转换在底层不会改变地址值,仅改变编译器对指针指向内存的解析规则,因此所有调用都能正确取出并输出目标值。若指针转换后指向的内存类型不匹配,解引用会触发未定义行为(比如将指向int的void*转成double*后解引用)。

内容的提问来源于stack exchange,提问作者Bomel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 23:24:56