【问题标题】:Convert Bytes to Int / uint in C在 C 中将字节转换为 Int / uint
【发布时间】:2012-08-27 17:52:13
【问题描述】:

我有一个无符号字符数组[248];用字节填充。像 2F AF FF 00 EB AB CD EF ..... 这个数组是我的字节流,我将来自 UART (RS232) 的数据存储为缓冲区。

现在我想将字节转换回我的 uint16 和 int32。

在 C# 中,我使用了 BitConverter 类来执行此操作。例如:

byte[] Array = { 0A, AB, CD, 25 };
int myint1 = BitConverter.ToInt32(bytes, 0);
int myint2 = BitConverter.ToInt32(bytes, 4);
int myint3 = BitConverter.ToInt32(bytes, 8);
int myint4 = BitConverter.ToInt32(bytes, 12);
//...
enter code here
Console.WriteLine("int: {0}", myint1); //output Data...

C 中有类似的函数吗? (没有 .net,我使用 KEIL 编译器,因为代码在微控制器上运行)

问候 山姆

【问题讨论】:

  • 本网站使用问答格式 - 请不要编辑问题以包含答案。无论如何,您在问题中编辑的答案也是错误的。

标签: c arrays serialization int byte


【解决方案1】:

是的,有。假设您的字节位于:

uint8_t bytes[N] = { /* whatever */ };

我们知道,一个 16 位整数只是串联的两个 8 位整数,即一个是 256 的倍数,或者移位 8:

uint16_t sixteen[N/2];

for (i = 0; i < N; i += 2)
    sixteen[i/2] = bytes[i] | (uint16_t)bytes[i+1] << 8;
             // assuming you have read your bytes little-endian

同样适用于 32 位:

uint32_t thirty_two[N/4];

for (i = 0; i < N; i += 4)
    thirty_two[i/4] = bytes[i] | (uint32_t)bytes[i+1] << 8
        | (uint32_t)bytes[i+2] << 16 | (uint32_t)bytes[i+3] << 24;
             // same assumption

如果字节是大端读取,当然你颠倒顺序:

bytes[i+1] | (uint16_t)bytes[i] << 8

bytes[i+3] | (uint32_t)bytes[i+2] << 8
    | (uint32_t)bytes[i+1] << 16 | (uint32_t)bytes[i] << 24

请注意,存储整数的字节序和运行架构的字节序存在差异。此答案中提到的字节序是存储的整数,即bytes 的内容。自 endian-ness is taken care of when shifting 以来,这些解决方案与运行架构的字节序无关。

【讨论】:

  • 然后你移入最低有效位而不是最高有效位。
  • @twall,我认为你的意思是字节。
  • @sam,看我的编辑。另外,试着读一点二进制数。我正在做的是简单的乘法。
  • 愚蠢的问题,但是我的 Array[100] 是一个 char 数组,但这有关系吗,因为你们写了 uint8_t bytes[N]
  • @sam,如果您系统上的char 已签名,那么是的,这很重要。想象一下0xFF。如果您查看为已签名,则为 -1。所以不是加到 255,而是减去 1,这不是你想要的。顺便说一句,unsigned charuint8_t 是一样的。
【解决方案2】:

如果是little-endian,你不能只使用memcpy吗?

memcpy((char*)&myint1, aesData.inputData[startindex], length);

【讨论】:

    【解决方案3】:
                char letter = 'A';
                size_t filter = letter;
                filter = (filter <<  8 | filter);
                filter = (filter << 16 | filter);
                filter = (filter << 32 | filter);
                printf("filter: %#I64x \n", filter); 
    

    结果:“过滤器:0x4141414141414141”

    【讨论】:

      【解决方案4】:

      在 C 中没有标准函数可以为您执行此操作。您必须自己将字节组装回 16 位和 32 位整数。小心字节序!

      这是一个简单的小端示例:

      extern uint8_t *bytes;
      uint32_t myInt1 = bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24);
      

      对于大端系统,它只是相反的顺序:

      uint32_t myInt1 = (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3];
      

      你也许可以逃脱:

      uint32_t myInt1 = *(uint32_t *)bytes;
      

      如果您注意对齐问题。

      【讨论】:

      • 在转换之前,我会将每个 bytes[] 转换为 uint32_t。如上所述,在进行移位之前,它们将被强制转换为 ints,但 int 不必是 32 位。
      • 这样比较安全,同​​意。
      • 假设bytes 是本地字节序,你会遇到什么样的对齐问题?或者,我猜,什么样的情况会使对齐成为问题?
      • *(uint32_t *)bytes 导致未定义的行为(严格的别名冲突)
      • 谢谢!最佳答案!你拯救了我的一天!
      猜你喜欢
      • 1970-01-01
      • 2014-07-31
      • 2011-05-11
      • 1970-01-01
      • 1970-01-01
      • 2020-03-01
      • 2013-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多