一小段困惑的C代码请教

[复制链接]
 楼主| if_for 发表于 2017-12-2 16:17 | 显示全部楼层 |阅读模式
本帖最后由 if_for 于 2017-12-2 16:30 编辑

最近开发中遇到一个问题不解,跟大家分享请教:
开发环境:Keil MDK 5.15
函数功能:把四个字节的unsigned char转换成unsignedint/float
函数实现方法1:
static uint32_t bytes_to_uint32(const unsigned char * data)
{
        return *(const uint32_t*)(data);
}

static float bytes_to_float(const unsigned char * data)
{
        return *(const float*)(data);
}
这种写**报错---usage fault。
个人觉得这样写应该没有问题的,有点不理解?如果有朋友知道,望不吝赐教。
hxfxt 发表于 2017-12-2 17:19 | 显示全部楼层
你这样访问考虑过剩下三个字节(除了char 本身的1字节)的感受吗?float 和uint32_t 是4字节的,unsigned char是单字节的
zxq6 发表于 2017-12-2 17:21 来自手机 | 显示全部楼层
我一般使用联合体
 楼主| if_for 发表于 2017-12-2 17:27 | 显示全部楼层
hxfxt 发表于 2017-12-2 17:19
你这样访问考虑过剩下三个字节(除了char 本身的1字节)的感受吗?float 和uint32_t 是4字节的,unsigned c ...

是这样的,char(1字节)的地址提供一个起始地址,从这个地址开始的4个字节的内容就是目标内容,取出来作为uint32_t返回
 楼主| if_for 发表于 2017-12-2 17:27 | 显示全部楼层
zxq6 发表于 2017-12-2 17:21
我一般使用联合体

我试过,使用联合体程序OK。
 楼主| if_for 发表于 2017-12-2 17:31 | 显示全部楼层
hxfxt 发表于 2017-12-2 17:19
你这样访问考虑过剩下三个字节(除了char 本身的1字节)的感受吗?float 和uint32_t 是4字节的,unsigned c ...

使用联合体来实现这个功能是没问题的,只是感觉奇怪,用指针应该也是没问题的,可偏偏有问题?
linqing171 发表于 2017-12-2 19:19 | 显示全部楼层
地址不四字节对齐的原因,加pack修饰指针。
zyj9490 发表于 2017-12-2 21:53 | 显示全部楼层
如果传进去是连续的字节数组常量,应是可以的,如果不是,还是内存溢出的问题。
hxfxt 发表于 2017-12-2 22:18 | 显示全部楼层
if_for 发表于 2017-12-2 17:31
使用联合体来实现这个功能是没问题的,只是感觉奇怪,用指针应该也是没问题的,可偏偏有问题? ...

联合体你放个4字节的放个单字节的,分配的内存空间当然是4字节的!你上面的程序其余三字节的访问你绝的合理吗?你知道那三字节原先放的什么东西吗?
hxfxt 发表于 2017-12-2 22:25 | 显示全部楼层
if_for 发表于 2017-12-2 17:27
是这样的,char(1字节)的地址提供一个起始地址,从这个地址开始的4个字节的内容就是目标内容,取出来作 ...

那后面的地址空间你确定放的什么东西吗?是否允许访问呢?
renxiaolin 发表于 2017-12-2 22:53 | 显示全部楼层
不要学c了,没前途
 楼主| if_for 发表于 2017-12-3 17:09 | 显示全部楼层
hxfxt 发表于 2017-12-2 22:18
联合体你放个4字节的放个单字节的,分配的内存空间当然是4字节的!你上面的程序其余三字节的访问你绝的合 ...

u8 部分是数组,所以是连续的
renxiaolin 发表于 2017-12-3 18:00 | 显示全部楼层
浮点型在内存的表示跟整型不一样,你看看是不是这个问题
computer00 发表于 2017-12-4 09:33 | 显示全部楼层
有可能是对齐问题。一般处理器要求在访问int或float时,地址需要4字节对齐,如果不对齐,就会抛异常。
最好是先定义好一个int或float型数据,然后用memcpy把目标数据拷贝进去,这样就不存在对齐问题了。

static uint32_t bytes_to_uint32(const unsigned char * data) {
         uint32_t ret;
         memcpy(&ret, data, sizeof(ret);
         return ret;
}

static float bytes_to_float(const unsigned char * data) {
         float ret;
         memcpy(&ret, data, sizeof(ret);
         return ret;
}
icz 发表于 2017-12-4 16:41 | 显示全部楼层
以指针访问数据是要和指针的原型相同且地址是分配好的才行,有疑问联系我,微信:jyucyz
ta1ent 发表于 2017-12-4 20:37 | 显示全部楼层
还是老老实实用联合比较好,这样写会出现一些莫名其妙的内存错误。
xcvista 发表于 2017-12-4 21:40 | 显示全部楼层
估计是内存对齐的问题。ARM Cortex-M 默认不允许非对齐访问,访问 4 字节的 uint32_t 地址必须是对齐到 4 字节。你可以用联合,也可以用 memcpy。
xcvista 发表于 2017-12-4 21:45 | 显示全部楼层
renxiaolin 发表于 2017-12-2 22:53
不要学c了,没前途

那么您建议学什么?
@若水 发表于 2017-12-4 22:14 | 显示全部楼层
zxq6 发表于 2017-12-2 17:21
我一般使用联合体

我也是
renxiaolin 发表于 2017-12-5 08:35 | 显示全部楼层
xcvista 发表于 2017-12-4 21:45
那么您建议学什么?

python,golang
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

111

帖子

2

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