[技术问答] 别再强制类型转化了,来告诉你个小技巧

[复制链接]
1922|19
 楼主| dspmana 发表于 2025-2-18 05:36 | 显示全部楼层 |阅读模式
#include <stdio.h>
2#include <stdlib.h>
3
4/*************************************
5 * Fuction:精度损失
6 * Author : (公众号:最后一个bug)
7 ************************************/
8 int main(int argc, char *argv[]) {
9    float fVal1 = 0;
10    int   sVal1 = 60012502;
11    int   sVal2 = 60012501;
12
13    printf("sizeof(int) = %d\n",sizeof(int));
14    printf("sizeof(float) = %d\n",sizeof(float));
15
16    fVal1 = (float) sVal1;
17    printf("fVal1 = %f\n",fVal1);
18
19    fVal1 = (float) sVal2;
20    printf("fVal1 = %f\n",fVal1);
21
22
23    sVal1 = (int) fVal1;
24    printf("sVal1 = %d\n",sVal1);
25
26    sVal2 = (int) fVal1;
27    printf("sVal2 = %d\n",sVal2);
28
29    if(sVal1 == sVal2)
30    {
31        printf("sVal1 == sVal2\n");     
32    }
33    else
34    {
35        printf("sVal1 != sVal2\n");
36    }
37
38   
39
40    return 0;
41}、
其实对于内存上所保存的数据是没有具体类型的,所谓数据类型仅仅只是以怎样一种方式进行数据的访问罢了,我们通过指针来进行访问就很好的说明了这个问题,例如int *ptr,表示ptr所指向的地址以int类型进行访问,如果把ptr改为float类型即float *ptr,其便以float类型来访问地址所对应的内存。

    既然像第二小节说的float类型的参数保存区无法修改了,那么我们就想办法直接绕过float类型来进行数据访问。

参考demo:
1#include <stdio.h>
2#include <stdlib.h>
3
4/*************************************
5 * Fuction: 两个宏--可以继续扩展
6 * Author : (公众号:最后一个bug)
7 ************************************/
8#define SET_INT_VAL(addr,val)  *((int*)(&addr)) = val
9#define SET_GET_VAL(addr)      *((int*)(&addr))
10
11/*************************************
12 * Fuction: 改善小技巧
13 * Author : (公众号:最后一个bug)
14 ************************************/
15 int main(int argc, char *argv[]) {
16    float fVal1 = 0;
17    int   sVal1 = 60012502;
18
19    printf("sizeof(int)   = %d\n",sizeof(int));
20    printf("sizeof(float) = %d\n",sizeof(float));
21
22    //接受整形数据到float数据内存
23    SET_INT_VAL(fVal1,sVal1);
24
25    //float数据内存获得整形数据
26    printf("SET_GET_VAL(fVal1) = %d\n",SET_GET_VAL(fVal1));
27    printf("            sVal1  = %d\n",sVal1);
28
29   
30
31    return 0;
32}


分析一下:
Demo中通过两个宏进行地址的类型处理转化,对float内存进行直接访问来保存整形数据,同样后面通过地址的直接访问来获得整形数据,这样就可以绕开float类型的处理问题。

同时大家也要注意其本地类型占用字节大小(float)需>=所要转化的类型占用字节大小(int),否则会造成数据的篡改,这样就会造成更多麻烦。

其实这里仅仅只用float进行存储参数的设计,原本就存在设计上的缺陷,可以通过共联体,或者无类型内存设计方案进行处理,这样就不会出现类似的问题了。

永久冻结 发表于 2025-8-28 12:59 | 显示全部楼层
使用指针操作和 unions 共享内存,或用标准库函数(如 memcpy)安全转换类型,避免强制转换导致的未定义行为和潜在错误。
永久冻结 发表于 2025-8-28 13:03 | 显示全部楼层
使用匿名联合体(union)共享内存空间,通过不同成员访问同一块数据,安全实现类型转换,避免强制转换的风险与未定义行为。
benjaminka 发表于 2025-9-8 11:03 | 显示全部楼层
可以利用编译器的隐式类型转换              
uiint 发表于 2025-9-8 14:02 | 显示全部楼层
从源头避免类型不匹配,而非事后补救。
一点点晚风 发表于 2025-9-16 16:20 | 显示全部楼层
处理类型转换时,试试用语言自带的安全方法替代强制转换,避免报错或数据丢失。比如 Python 用int('123')而非强制转,Java 用Integer.parseInt("456");JavaScript 可用Number('789')或parseFloat('3.14')。这些方**先校验数据合法性,还能配合条件判断处理异常,让转换更稳妥,代码也更易维护。
jonas222 发表于 2025-9-17 21:22 | 显示全部楼层
比如将float拆分为字节,或在uint32_t与int32_t间转换
loutin 发表于 2025-9-18 22:13 | 显示全部楼层
优先利用C语言的隐式转换规则              
sanfuzi 发表于 2025-9-19 07:23 | 显示全部楼层
类型安全更可控              
ccook11 发表于 2025-9-19 08:28 | 显示全部楼层
转换指针是否满足目标类型对齐?              
earlmax 发表于 2025-9-19 12:23 | 显示全部楼层
在进行数**算时,通过合理安排操作数的类型,可以让编译器按照预期的方式进行隐式类型转换。
ingramward 发表于 2025-9-19 13:28 | 显示全部楼层
const数据被转换后修改?                      
jtracy3 发表于 2025-9-19 21:51 | 显示全部楼层
如果有一个 int 类型的变量 i,将其赋值给一个 long 类型的变量 l 时,编译器会自动将 i 转换为 long 类型,无需显式转换。
belindagraham 发表于 2025-9-20 08:50 | 显示全部楼层
处理硬件寄存器、网络协议头等需要直接操作二进制数据的场景。
qiufengsd 发表于 2025-9-20 09:40 | 显示全部楼层
函数参数传递指针时,避免将 void* 强制转换为具体类型
wangdezhi 发表于 2025-9-20 10:57 | 显示全部楼层
当需要进行多次类型转换时,使用中间变量可以使代码更清晰易读。
primojones 发表于 2025-9-20 12:56 | 显示全部楼层
通过错误类型的指针访问同一内存              
macpherson 发表于 2025-9-20 15:06 | 显示全部楼层
若频繁需要强制转换,重新设计数据结构或接口。
modesty3jonah 发表于 2025-9-20 15:48 | 显示全部楼层
避免未定义行为              
maudlu 发表于 2025-9-20 17:00 | 显示全部楼层
要将字符串转换为整数,可以使用 atoi() 函数;要将字符串转换为浮点数,可以使用 atof() 函数。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

45

主题

2858

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部