将字符转换为短

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&amp; 0xFF00char 上将始终产生 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];

【讨论】:

以上是关于将字符转换为短的主要内容,如果未能解决你的问题,请参考以下文章

将字符串转换为短 C# 时出现格式异常

将十六进制转换为短和长

将位数组转换为短数组

在 JavaCard 中将字节转换为短字节

如何将二进制资源转换为短数组?

将范围-1到1的浮点数转换为短的快速方法?