将字符转换为短
Posted
技术标签:
【中文标题】将字符转换为短【英文标题】:Convert char to short 【发布时间】:2014-09-11 12:22:38 【问题描述】:我需要将数据从 2 个char
(8 位长)复制到一个 short
(16 位长)。我尝试了两种不同的方法,但无法正常工作。
void char2short(char* pchar, short* pshort)
memcpy(pshort , pchar + 1 , 1);
memcpy(pshort + 1, pchar , 1);
还有一个:
void char2short(char* pchar, short* pshort)
short aux;
aux = ((*pchar & 0x00FF) << 8) | ((*(pchar+1) & 0xFF00) >> 8);
*pshort = aux;
【问题讨论】:
你不能这样使用 memcpy,因为 ist 不能自动转换这些数据类型。您需要遍历 src 数组并将每个值转换为短 你需要知道short是否表示为little-endian or big-endian。 你需要知道 pchar 和 pshort 的字节序。如果它们相同,请使用memcpy((void *)pshort, (const void*)pchar, sizeof(short));
【参考方案1】:
#include <stdio.h>
void char2short(unsigned char* pchar, unsigned short* pshort)
*pshort = (pchar[0] << 8) | pchar[1];
int main()
unsigned char test[2];
unsigned short result = 0;
test[0] = 0xAB;
test[1] = 0xCD;
char2short(test, &result);
printf("%#X\n",result);
return 0;
这样就可以了。
【讨论】:
字节序在这里不是问题,至少在假设pchar
下的数据不会根据系统的字节序而改变时,在您的示例中并非如此。
如果这是一个 16 位系统,当将有符号数左移 8 位时会出现问题。这会调用未定义的行为。在编写 bit hacks 时不要使用草率的默认整数类型!
几年后在这里查看并告诉你你的答案帮助我完成我的论文,从而获得我的学位!你摇滚!
恭喜。很高兴听到我可以帮助你。【参考方案2】:
假设 pchar
是一个包含 2 个字符的数组,那么:
*pshort = (uint16_t)(((unsigned int)pchar[0]) |
(((unsigned int)pchar[1])<<8));
附:这适用于小字节序。
【讨论】:
字节序在这里不是问题,至少在假设pchar
下的数据不会根据系统的字节序而改变时。【参考方案3】:
其他人没有解释为什么你的代码不起作用,所以我会快速尝试一下:
memcpy(pshort , pchar + 1 , 1);
memcpy(pshort + 1, pchar , 1);
添加到指针TYPE * p
将指针移动sizeof( TYPE )
的增量(所以它确实指向下一个元素,请记住这只是定义 if inside数组)。所以虽然pchar + 1
是正确的,但pshort + 1
不是(因为它正在处理下一个short
)。
aux = ((*pchar & 0x00FF) << 8) | ((*(pchar+1) & 0xFF00) >> 8);
Errr.... 右手边的损坏方式不止一种。首先,*(pchar+1)
是char
,& 0xFF00
在char
上将始终产生 0(因为char
开始时只有 8 位,至少在现代机器上......)。然后你把那 8 位右移...?
如果您没有在左侧使用 0x00FF(将 *pchar
提升到右侧操作数的宽度)但是(char
-sized),以防万一您不知道0xFF,该操作的结果仍然是 char
类型,并且将这 8 位向左移动也没有多大意义(因为类型不会神奇地扩展)。
另一种尚未提及的解决方法是union
:
#include <stdio.h>
struct chars_t
// could also go for char[2] here,
// whichever makes more sense semantically...
char first;
char second;
;
union combo_t
// elements of a union share the memory, i.e.
// reside at the same address, not consecutive ones
short shrt;
struct chars_t chrs;
;
int main()
union combo_t x;
x.chrs.first = 0x01;
x.chrs.second = 0x02;
printf( "%x", x.shrt );
return 0;
如果您在更大的上下文中使用它,请注意结构填充。
【讨论】:
联合将使代码依赖于字节序。在大端系统上,您将获得预期的结果 0x0102,但在小端系统上,您将获得 0x0201。然后确实存在填充危险。所以联合不是一个好主意,改用位移位。 @Lundin:根据您的需要,依赖字节序的结果实际上可能就是您正在寻找的结果。 ;-) 但我同意,union
有点狡猾。为了完整起见,我将其包括在内。
你为什么要故意编写依赖字节序的代码?无论系统如何,Endianess 都是 100% 的坏事。
@Lundin:我曾经遇到过一两次系统,在这些系统中,现有的 API要求我编写根据字节序而表现不同的代码。 (通常是因为对方一开始就懒得照顾字节序。)有时更改现有的 API 不是一种选择。【参考方案4】:
进行按位运算时,请使用具有已知符号的固定大小实数的稳健代码。这将防止您编写与隐式类型转换相关的错误,从而导致意外的签名。 char
类型特别危险,因为它具有实现定义的签名。它不应该用于存储数字。
#include <stdint.h>
void char2short(const uint8_t* pchar, uint16_t* pshort)
*pshort = ((uint16_t)pchar[0] << 8) | (uint16_t)pchar[1];
【讨论】:
以上是关于将字符转换为短的主要内容,如果未能解决你的问题,请参考以下文章