简体   繁体   English

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

[英]Typecasting Arrays for Variable Width Access

Sorry, I am not sure if I wrote the title accurately.对不起,我不确定我是否准确地写了标题。

But first, here are my constraints:但首先,这是我的限制:

  1. Array[], used as a register map, is declared as an unsigned 8-bit array (uint8_t), this is so that indexing(offset) is per byte. Array[],用作寄存器 map,被声明为无符号 8 位数组 (uint8_t),这样索引(偏移)是每个字节的。
  2. Data to be read/written into the array has varying width (8-bit, 16-bit, 32-bit and 64-bit).要读取/写入数组的数据具有不同的宽度(8 位、16 位、32 位和 64 位)。
  3. Very Limited Memory and Speed is a must.非常有限的 Memory 和速度是必须的。

What are the caveats in doing the following执行以下操作有哪些注意事项

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;
}

I know i could try writing the data per byte, but that would be slow due to bit shifting.我知道我可以尝试按字节写入数据,但是由于位移,这会很慢。

Is there going to be a significant problem with this usage?这种用法会不会有很大的问题? I have run this on my hardware and have not seen any problems so far, but I want to take note of potential problems this implementation might cause.我已经在我的硬件上运行了它,到目前为止还没有发现任何问题,但我想注意这个实现可能导致的潜在问题。

Is there going to be a significant problem with this usage?这种用法会不会有很大的问题?

It produces undefined behavior.它会产生未定义的行为。 Therefore, even if in practice that manifests as you intend on your current C implementation, hardware, program, and data, you might find that it breaks unexpectedly when something (anything) changes.因此,即使在实践中,在您当前的 C 实现、硬件、程序和数据上表现出您的意图,您也可能会发现当某些(任何东西)发生变化时它会意外中断。

Even if the compiler implements the cast and dereference in the obvious way (which it is not obligated to do, because UB) misaligned accesses resulting from your approach will at least slow many CPUs, and will produce traps on some.即使编译器以明显的方式实现强制转换和取消引用(它没有义务这样做,因为 UB),由您的方法导致的未对齐访问至少会减慢许多 CPU,并且会在一些 CPU 上产生陷阱。

The standard-conforming way to do what you want is this:做你想做的符合标准的方法是这样的:

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;
}

This is not necessarily any slower than your version, and it has defined behavior as long as you do not overrun the bounds of your array.这不一定比您的版本慢,并且只要您不超出数组的范围,它就已经定义了行为。

This is probably fine.这可能没问题。 Many have done things like this.很多人都做过这样的事情。 C performs well with this kind of thing. C 在这种情况下表现良好。

Two things to watch out for:需要注意的两件事:

  1. Buffer overruns.缓冲区溢出。 You know those zero-days like Eternal Blue and hacks like WannaCry?你知道那些像 Eternal Blue 这样的零日和像 WannaCry 这样的黑客吗? Many of them exploited bugs in code like yours.他们中的许多人利用了像您这样的代码中的错误。 Malicious input caused the code to write too much stuff into data structures like your uint8_t Array[0x100] .恶意输入导致代码将太多内容写入数据结构,如uint8_t Array[0x100] Be careful.当心。 Avoid allocating buffers on the stack (as function-local variables) as you have done because clobbering the stack is exploitable.避免像您所做的那样在堆栈上分配缓冲区(作为函数局部变量),因为破坏堆栈是可利用的。 Make them big enough.让它们足够大。 Check that you don't overrun them.检查你没有超越他们。

  2. Machine byte ordering vs. network byte ordering, aka endianness .机器字节排序与网络字节排序,也就是字节序 If these data structures move from machine to machine over the net you may get into trouble.如果这些数据结构通过网络在机器之间移动,您可能会遇到麻烦。

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

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