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

memcpy是否属于类型转换?float拷贝到long场景解析

关于这段memcpy代码的原理解答

你在分析第三方软件时遇到的代码如下:

memcpy((void *)&vardata.value, (void *)&fvalue, sizeof(vardata.value));

已知前提:

  • vardata.value 为long类型变量
  • fvalue 为float类型变量

此处memcpy的具体执行逻辑

memcpy的核心行为是按字节顺序拷贝内存原始内容,全程不会对数据做任何数值层面的转换处理。
结合你运行得到的固定输出结果,可以判断当前运行环境中long类型和float类型长度均为4字节,执行逻辑如下:

  1. 函数以fvalue的内存地址为起点,读取长度为sizeof(vardata.value)也就是4字节的原始二进制数据
  2. 把读到的4字节数据原封不动写入vardata.value所在的内存地址,覆盖该变量原来存储的值
  3. 整个过程完全不校验源地址和目标地址对应的变量类型,只做纯内存层面的字节复制。
    如果当前环境long长度为8字节(比如64位类Unix系统默认配置),这段代码会越界读取fvalue变量后方4字节的未知内存数据,最终得到的vardata.value值是不可预期的。

fvalue为12.65时vardata.value的取值来源

你打印得到的1095394918是完全符合逻辑的结果:
float类型遵循IEEE 754单精度浮点数编码规则,12.65编码后的32位二进制对应的十六进制值为0x414A6666,把这串二进制数据直接按有符号long类型解析成十进制,刚好就是1095394918。
输出里fvalue仍然显示12.65也很好理解:memcpy只是复制了fvalue的内存内容,并没有修改fvalue本身存储的数据。

该操作是否属于类型转换

这不是C语言标准定义的常规类型转换:

  • 常规的数值类型转换(比如写(long)fvalue)会做数值语义上的适配,12.65转long会得到截断后的整数值12,转换前后的数值逻辑是自洽的。
  • 这种直接拷贝内存二进制的写法属于类型双关(type punning),是底层代码里偶尔会用到的技巧:直接把同一段内存二进制内容交给不同类型的变量解析,拿到该编码在其他类型规则下的值,常用来做浮点数二进制拆解、网络协议字段解析这类场景。这种写法对类型长度、字节序、内存对齐的要求很高,写不对很容易触发未定义行为。

你用printf("VAL 1 = %ld VAL 2 = %.2f\n", vardata.value, fvalue);能得到符合预期的打印结果,本质是刚好vardata.value拿到的4字节内容和float的原始内存完全一致,且long和float的参数传递规则在当前环境下没有触发异常而已。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:06:28