【问题标题】:casting pointers in a buffer在缓冲区中转换指针
【发布时间】:2015-01-31 05:50:11
【问题描述】:

假设我有一个充满数据的缓冲区,并且我从网络上获取了它。

uint8_t buffer[100];

现在想象这个缓冲区有不同的字段。有些是 1 个字节,有些是 2 个字节,有些是 4 个字节。所有这些字段都打包在缓冲区中。

现在假设我想获取 16 位字段之一的值。假设在缓冲区中,该字段是这样存储的:

buffer[2] = one byte of two byte field
buffer[3] = second byte of two byte field

我可以像这样获取这个值:

uint16_t* p_val;

p_val = (int16_t*) &buffer[2];
or
p_val = (int16_t*) (buffer + 2);

printf("value: %d\n", ntohs(*p_val));

这种方法有什么问题吗?或者我应该注意的对齐问题?

【问题讨论】:

  • 两个问题:字节序和对齐。前者可能更重要,因为编译器应该通过添加更多代码来为您处理后者。但是字节顺序你必须自己处理。
  • 假设我从以太网数据包中获得了缓冲区,解引用时的 ntohs 会解决字节顺序问题吗?。
  • @user1764386 不,因为您不知道编码机器的字节序。这是数据内容?
  • 如果您正在查看远程计算机写入的数据内容,您如何判断它是编码为 MSB-LSB 还是 LSB-MSB?

标签: c pointers


【解决方案1】:

正如评论中所说,是的,您提出的方法存在问题。尽管它可能在目标机器上工作,或者它可能碰巧在给定的情况下工作,但一般来说,在不同的指针类型之间进行转换是不安全的。 (也有例外。)

要正确考虑对齐和字节顺序,您可以这样做:

union convert {
    uint32_t word;
    uint16_t halfword[2];
    uint8_t bytes[4];
} convert;

uint16_t result16;

memcpy(convert.bytes, buffer + offset, 2);

/* assuming network byte order: */
result16 = ntohs(convert.halfword[0]);

如果您可以控制数据格式,那么网络字节顺序是一个不错的选择,因为程序不需要明确地确定、假设或知道运行它的机器的字节顺序。

【讨论】:

    猜你喜欢
    • 2013-04-25
    • 2021-03-13
    • 2018-04-19
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-02
    相关资源
    最近更新 更多