在 C++ 中的微控制器上执行转换为较小类型的推荐方法

Recommended way to perform a cast to a smaller type on micro controller in C++

我正在为基于 32 位微控制器的 Arduino Due 编程。我想读取一个 ADC 结果寄存器(如果我是对的,它的宽度为 32 位,但它的真正最大宽度为 12 位,这是 ADC 的分辨率),并将其写入数组中的给定位置宽度为 16 位的整数。

这个有效:

volatile uint16_t Buf[nchannels];

[... some code...]

void ADC_Handler() {
  for (int i = 0; i < nchannels; i++)
  {
      Buf[i] = (volatile uint16_t) * (ADC->ADC_CDR + channels[i]); // my modification
  }
   FlagConversion = true;
}

但是使用更“显式”的演员表是行不通的:

Buf[i] = dynamic_cast<volatile uint16_t *>(ADC->ADC_CDR + channels[i]);

产生:

“错误:不能dynamic_cast '(((RoReg*)1074528336) + ((sizetype)(((unsigned int)channels[i]) * 4)))'(类型'RoReg* {aka volatile long unsigned int*}') 键入 'volatile uint16_t* {aka volatile short unsigned int*}'(目标不是指针或对 class 的引用)"

以及静态和重新解释转换的类似不明确错误:

“错误:不能dynamic_cast '(((RoReg*)1074528336) + ((sizetype)(((unsigned int)channels[i]) * 4)))'(类型'RoReg* {aka volatile long unsigned int*}') 键入 'volatile uint16_t* {aka volatile short unsigned int*}'(目标不是指针或对 class 的引用)"

“错误:从 'volatile uint16_t* {aka volatile short unsigned int*}' 到 'uint16_t {aka short unsigned int} 的无效转换”

进行转换的'safe'方法是首先取消引用指向 32 位数据的指针,然后屏蔽掉该数据项的高 16 位,然后 static_cast 结果到您的 16 位目标数据:

    Buf[i] = static_cast<volatile uint16_t>( *(ADC->ADC_CDR + channels[i]) & 0x0FFFF );

最好始终使用 'simplest' 形式的转换,并尽可能避免使用 C-style 转换和 reinterpret_cast。在这种情况下,强制转换指针没有什么意义,而且 比 convert/cast 数据本身更安全和更简单

实际上,0x0FFFF 的屏蔽严格来说是完全不必要和多余的。但是,它让您的代码的任何未来 reader 清楚地知道您确实知道自己在做什么!