在C中读取变量作为更大的类型

时间:2014-05-16 14:17:14

标签: c c99

当读取或写入缓冲区时,我认为通常需要访问大于缓冲区(指针)类型的数据。到目前为止,我已经提出了三种截然不同的方法,但我想知道是否有这种语言功能或公认的标准做法。选项c提供了最大的灵活性,它可以处理结构和数组以及整数类型。

#include <stdio.h>
#include <stdint.h>

#define BUFFER_SIZE 10
#define ADDRESS 6

uint8_t buffer[BUFFER_SIZE] =
{
    [ADDRESS] = 0x37,
    [ADDRESS+1] = 0x42,
};

int main(void)
{
    uint16_t a = buffer[ADDRESS] + (buffer[ADDRESS + 1]<<8);
    uint16_t b = *(buffer + ADDRESS) + (*(buffer + ADDRESS + 1)<<8);
    uint16_t c = *((uint16_t *) (buffer + ADDRESS));

    printf("a: 0x%x\n", a);
    printf("b: 0x%x\n", b);
    printf("c: 0x%x\n", c);

    return 0;
}

我不关心字节序,因为与缓冲区的所有交互都在单个嵌入式程序中;具有字节顺序安全性的外部接口是独立提供的。最感兴趣的标准是C99,但欢迎参考任何标准。

3 个答案:

答案 0 :(得分:4)

前两个是等效的,此处buffer[ADDRESS]*(buffer + ADDRESS)

相同
uint16_t a = buffer[ADDRESS] + (buffer[ADDRESS + 1]<<8);
uint16_t b = *(buffer + ADDRESS) + (*(buffer + ADDRESS + 1)<<8);

最后一个调用未定义的行为,因为它违反了C别名规则(C99, 6.5p7)并且可能会破坏对齐:

uint16_t c = *((uint16_t *) (buffer + ADDRESS));

总而言之,选择第一个,因为它更具可读性。

答案 1 :(得分:3)

ab的代码是等效的,因为a[i]*(a + i)的简写。

c的代码调用未定义的行为,因为它可能使用非对齐访问。如果您知道您的机器处理未对齐的访问,并且拥有一个愉快的编译器,它可能会起作用。但不建议这样做,因为它可能会意外中断。

答案 2 :(得分:1)

无论数组缓冲区还是malloc ed缓冲区,底层活动都是从一个位置到另一个位置的任意字节的任意复制。对此的标准方法是memcpy()

uint16_t d;
memcpy(&d, &buffer[ADDRESS], sizeof(d));

Ideone example已更新。