简体   繁体   English

从char数组中提取2nd和3rd值,并将其强制转换为short(2个字节)。 在C中

[英]Extract 2nd and 3rd value from char array and cast it as short (2 bytes). In C

Say I have an unsigned char (or byte) array. 说我有一个无符号字符(或字节)数组。 I want to take array[1] and array[2] from memory and cast it as short int (2 bytes). 我想从内存中获取array [1]和array [2]并将其强制转换为short int(2个字节)。 Something similar to how a union works, but not starting from the first byte. 与联合的工作方式类似,但不是从第一个字节开始。

Example: 例:

#include <stdio.h>

void main()
{
    unsigned char a[28];
    unsigned short t;

    a[0]=12;
    a[1]=10;
    a[2]=55;

    t=(short) *(a+1);

    printf("%i", t);
}

What I want is the value 14090 in decimal. 我想要的是十进制值14090。 Or 370Ah. 或370Ah。

Thank you. 谢谢。

EDIT: I forgot to say, but most of you understood from my example, I am working on a little-endian machine. 编辑:我忘了说,但是你们中的大多数人都从我的例子中了解到,我正在使用低端字节序的计算机。 An 8bit Atmel microcontroller. 8位Atmel微控制器。

It's very simple: 很简单:

unsigned short t = (a[2] << 8) | a[1];

Note, this assumes unsigned char is 8 bits, which is most likely the case. 注意,这假定unsigned char为8位,这很可能是这种情况。

The memory access operation (short)*(a+1) is not safe. 内存访问操作(short)*(a+1)不安全。

If a+1 is not aligned to short (ie, a+1 is not a multiple of sizeof short ), then the result of this operation depends on the compiler at hand. 如果a+1不与short对齐(即a+1不是sizeof short的倍数),则此操作的结果取决于手边的编译器。

Compilers that support unaligned load/store operations can resolve it correctly, while others will "round it down" to the nearest address which is aligned to short . 支持不对齐的加载/存储操作的编译器可以正确地对其进行解析,而其他编译器会将其“舍入” short对齐的最近地址。

In general, this operations yields undefined behavior. 通常,此操作会产生未定义的行为。

On top of all that, even if you know for sure that a+1 is aligned to short , this operation will still give you different results between Big-Endian architecture and Little-Endian architecture. 在最严重的是,即使你确实知道a+1 对准 short ,这种操作还是会给予你大端架构和little-endian架构之间不同的结果。

Here is a safe way to work-around both issues: 这是解决两个问题的安全方法:

short x = 0x1234;
switch (*(char*)&x)
{
    case 0x12: // Big-Endian
        t = (a[1] << 8) | a[2]; // Simulate t = (short)*(a+1) on BE
        break;
    case 0x34: // Little-Endian
        t = (a[2] << 8) | a[1]; // Simulate t = (short)*(a+1) on LE
        break;
}

Please note that the code above assumes the following: 请注意,上面的代码假定以下内容:

  • CHAR_BIT == 8
  • sizeof short == 2

This is not necessarily true on every platform (although it is mostly the case). 这不一定在每个平台上都适用(尽管多数情况下是这样)。

t= *(short *)(a+1);

You cast the pointer to the first element to a pointer-to-short, and then dereference it. 您将指向第一个元素的指针转换为短指针,然后取消引用。

Note that this is not very portable, and can go wrong if the machine is big endian or aligns data somehow. 请注意,这不是便携式的,如果计算机使用大字节序或以某种方式对齐数据,则可能会出错。 A better way would be: 更好的方法是:

t = (a[2] << CHAR_BIT) | a[1];

For full portability, you should check your endianness and see which byte to shift, and which one not to. 为了实现完全的可移植性,您应该检查字节序,并查看要移位的字节,以及不移位的字节。 See here how to check a machine's endianness 在这里查看如何检查机器的字节序

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM