用于可变宽度访问的类型转换数组

Typecasting Arrays for Variable Width Access

抱歉,我不确定我写的标题是否准确。

但首先,这是我的限制条件:

  1. Array[],用作寄存器映射,声明为无符号8位数组(uint8_t), 这样索引(偏移量)是按字节计算的。
  2. 要 read/written 进入数组的数据具有不同的宽度(8 位、16 位、32 位和 64 位)。
  3. 非常有限的内存和速度是必须的。

执行以下操作有哪些注意事项

uint8_t some_function(uint16_t offset_addr) //16bit address
{
  uint8_t Array[0x100];
  uint8_t data_byte = 0xAA;
  uint16_t data_word;
  uint32_t data_double = 0xBEEFFACE;

\ A. Storing wider-data into the array
*((uint32_t *) &Array[offset_addr]) = data_double;

\ B. Reading multiple-bytes from the array
data_word = *((uint16_t *) &Array[offset_addr]);
 
  return 0;
}

我知道我可以尝试按字节写入数据,但由于位移,这会很慢。

这种用法会出现严重问题吗? 我的硬件上有 运行 这个,到目前为止还没有发现任何问题,但我想注意这个实现可能导致的潜在问题。

这可能没问题。许多人都做过这样的事情。 C在这种事情上表现很好。

需要注意两点:

  1. 缓冲区溢出。你知道像永恒之蓝这样的零日攻击和像 WannaCry 这样的黑客攻击吗?他们中的许多人都利用了像您这样的代码中的错误。恶意输入导致代码向 uint8_t Array[0x100] 之类的数据结构中写入过多内容。当心。避免像您所做的那样在堆栈上分配缓冲区(作为函数局部变量),因为破坏堆栈是可利用的。让它们足够大。检查你没有超过它们。

  2. 机器字节排序与网络字节排序,又名 endianness。如果这些数据结构通过网络从一台机器移动到另一台机器,您可能会遇到麻烦。

Is there going to be a significant problem with this usage?

它会产生未定义的行为。因此,即使在实践中按照您对当前 C 实现、硬件、程序和数据的预期表现,您也可能会发现当某事(任何)发生变化时它会意外中断。

即使编译器以明显的方式实现转换和取消引用(它没有义务这样做,因为 UB),您的方法导致的未对齐访问至少会减慢许多 CPU,并且会在某些 CPU 上产生陷阱。

做你想做的符合标准的方法是这样的:

uint8_t some_function(uint16_t offset_addr) {
  uint8_t Array[0x100];
  uint8_t data_byte = 0xAA;
  uint16_t data_word;
  uint32_t data_double = 0xBEEFFACE;

\ A. Storing wider-data into the array
  memcpy(Array + offset_addr, &data_double, sizeof data_double);

\ B. Reading multiple-bytes from the array
  memcpy(&data_word, Array + offset_addr, sizeof data_word);
 
  return 0;
}

这不一定比您的版本慢,只要您不超出数组的范围,它就会定义行为。