如何使用 C 将长值(32 位)拆分为四个 char 变量(8 位)?
Posted
技术标签:
【中文标题】如何使用 C 将长值(32 位)拆分为四个 char 变量(8 位)?【英文标题】:How do I split up a long value (32 bits) into four char variables (8bits) using C? 【发布时间】:2010-04-30 19:46:06 【问题描述】:我有一个 32 位长的变量 CurrentPosition,我想将它分成 4 个 8 位字符。我将如何在 C 中最有效地做到这一点?我正在使用 8 位 MCU,8051 架构。
unsigned long CurrentPosition = 7654321;
unsigned char CP1 = 0;
unsigned char CP2 = 0;
unsigned char CP3 = 0;
unsigned char CP4 = 0;
// What do I do next?
我是否应该只用指针引用 CurrentPosition 的起始地址,然后将该地址加 8 2 4 次?
它是小尾数。
我还希望 CurrentPosition 保持不变。
【问题讨论】:
我正在使用 SDCC 并使用 Little Endian 格式 【参考方案1】: CP1 = (CurrentPosition & 0xff000000UL) >> 24;
CP2 = (CurrentPosition & 0x00ff0000UL) >> 16;
CP3 = (CurrentPosition & 0x0000ff00UL) >> 8;
CP4 = (CurrentPosition & 0x000000ffUL) ;
您也可以通过指针访问字节,
unsigned char *p = (unsigned char*)&CurrentPosition;
//use p[0],p[1],p[2],p[3] to access the bytes.
【讨论】:
1) 我需要用 (unsigned char) 转换这些吗? 2)这不会影响 CurrentPosition 吗? 1.前者需要强制转换 2。两种方法都不影响 CurrentPosition 前者不需要强制转换,但如果你不这样做,一些编译器会发出虚假警告,指出可能会丢失精度。 请注意,移位版本是字节序中性的,使其更便携。【参考方案2】:我认为你应该考虑使用联合:
union
unsigned long position;
unsigned char bytes[4];
CurrentPosition;
CurrentPosition.position = 7654321;
现在可以通过以下方式访问字节:CurrentPosition.bytes[0], ..., CurrentPosition.bytes[3]
【讨论】:
实践中的一个好主意,因为编译器可以将 int 分解为字节。理论上是个坏主意,因为联合的这种用法在 c 标准中是未定义的..(尽管不是所有的实现都可以正常工作) @Nils 从 C99 开始就已经很好地定义了带有联合的类型双关语。代码仍然依赖于字节序。【参考方案3】:如果您使用的是 8 位 MCU,则需要对整个 32 位变量进行移位。在这种情况下,最好使用指针算法读取 4 个字节的 CurrentPosition。演员:
unsigned char *p = (unsigned char*)&CurrentPosition;
不会更改 CurrentPosition,但如果您尝试写入 p[0],您将更改 CurrentPosition 的最低有效字节。如果您想要一份副本,请执行以下操作:
unsigned char *p = (unsigned char*)&CurrentPosition;
unsigned char arr[4];
arr[0] = p[0];
arr[1] = p[1];
arr[2] = p[2];
arr[3] = p[3];
并与 arr 一起工作。 (如果您想要最重要的字节首先更改这些分配中的顺序)。
如果您更喜欢 4 个变量,您显然可以这样做:
unsigned char CP1 = p[0];
unsigned char CP2 = p[1];
unsigned char CP3 = p[2];
unsigned char CP4 = p[3];
【讨论】:
如果不能直接移动 32 位 int,这个解决方案会更好。【参考方案4】:CP1 = (unsigned char)(CurrentPosition & 0xFF);
CurrentPosition >>= 8;
CP2 = (unsigned char)(CurrentPosition & 0xFF);
...
【讨论】:
这会改变 CurrentPosition 中的值,对吧?我想保持 CurrentPosition 不变。 是的,一种选择是制作 CurrentPosition 的副本并破坏副本。或者 nos 的答案是另一种选择。您使用指针的想法也是可能的。有很多方法可以做到这一点。【参考方案5】:unsigned char *CP = &CurrentPosition;
现在可以通过CP[n]
访问每个原始代码的 CPn。
【讨论】:
【参考方案6】:我知道这是不久前发布的。但对于仍在阅读该主题的任何人: 许多人采取顺序转移原始值的方法。为什么不让编译器为您完成工作。 使用联合 & 允许您将值存储在同一位置。定义一个由一个 32 位长变量(这将是您保存 CurrentPosition 的位置)和一个由 4 个字符变量组成的结构组成的联合。或者只是一个简单的 8 位整数数组。当您将 CurrentPosition 写入 long 变量时,它将存储在您读取 4 个 char 变量时访问的相同位置。这种方法的劳动强度要小得多,并且不允许编译器完成工作,而不是浪费时间和资源。
【讨论】:
这正是the second most upvoted answer 所建议的。以上是关于如何使用 C 将长值(32 位)拆分为四个 char 变量(8 位)?的主要内容,如果未能解决你的问题,请参考以下文章