【问题标题】:Strange behaviour when casting array char to array short将数组char转换为数组short时的奇怪行为
【发布时间】:2013-06-12 08:22:46
【问题描述】:

我有 2 个数组:第一个是 8 个 unsigned char,第二个是 4 个 unsigned short,对于某些算法兼容性问题,我需要将短数组与 char 数组的值一起使用,这样做我我在做一个循环

j = 0;
for(i=0; i<8; i+=2)
{
    short_array[j] = *(unsigned short*) (char_array + i);
    j++;
}

这里一切正常,但在之前的一些尝试中,我尝试了以下方法(这显然不是正确的答案)

j = 0;
for(i=0; i<8; i+=2)
{
    short_array[j] = (unsigned short*) *(&(char_array + i));
    j++;
}

问题:

假设以下char_array = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88} 当我做第一个 short_array = {0x1122, 0x3344, 0x5566, 0x7788} 但是当我做第二个时,short_array = {0x3344, 0x5566, 0x7788, ???}(其中 ??? 是未定义的,因为它是内存中的一个值并且可能会改变)。

你能解释一下为什么会这样吗?

PS:我的编译器套件是 Keil 的 C251

【问题讨论】:

  • &amp;(char_array + i) 甚至不应该编译。
  • @H2CO3 我非常同意这一点!这就是为什么我再次感到惊讶的原因,这是否可以在 gcc(或任何 C99)上编译?
  • 不,它没有。 OS X 上的clang 告诉我quirk.c:14:44: error: address expression must be an lvalue or a function designator
  • 所以我认为这是一个编译器问题(感谢您对其进行测试),我将查看汇编代码以了解这一点。如果 Keil 人读到这里,请考虑制作一个高效的编译器...
  • memcpy(short_array, char_array, sizeof short_array); 可能会起作用,具体取决于字节序。

标签: c arrays casting


【解决方案1】:

我已经比较了这两个解决方案(即使第二个不是有效的),这绝对是一个编译器问题,首先编译器不应该让我编译 &amp;(char_array + i) ,然后我发现(在检查汇编代码时) char_array 在第二种情况下在循环中访问它之前递增;并且在第一种情况下(正确的情况下)读取变量后进行增量。似乎没有比编译器实现问题更多的解释了……

【讨论】:

  • 您假设您的第一个代码块是正确的。不是,因为它取决于 char 数组的对齐方式和目标平台的字节顺序。责备编译器接受不正确的代码将无济于事。你应该从编写正确的代码开始。
  • 就像我对 It'sPete 所说的那样,我们完全确定目标的对齐和字节序;我咨询了当地的专家,并说这是针对这种特殊情况的最佳解决方案;我再次同意字节序和对齐对于数组非常重要。问题更多是关于为什么第二个选项会编译并生成奇怪的行为
【解决方案2】:

我建议手动读出 char 数组中的每个元素,并将每对 char 构建成一个 short。我知道可能有更快的方法,但是您隐式地跨过了您在 char 数组中指定的类型的界限。另外,我会声称我的版本在您的意图方面更容易阅读,尽管更笨拙。

也就是说,是这样的:

忽略第一个代码块...这就是我不睡觉时发生的事情!

j=0;
uint16_t temp;  // recommend to use these types for portability
for(i=0; i<8; i+=2) {
  temp = 0x0000;
  temp += (uint16_t)(char_array[i] << 8);
  temp += (uint16_t)(char_array[i+1]);
  short_array[j] = temp;
  j++;
}

另外,这是我在多考虑问题后想出的一个更快的方法,并给自己一个当之无愧的自我强加的代码审查。

j=0;
  for(i=0; i<8; i+=2) {
  short_array[j] = (char_array[i] << 8) | char_array[i+1];  // use bitwise operations
  j++;
}

【讨论】:

  • “隐式跨过类型的边界”,这是什么意思?我的第一个代码完美运行,这不是问题
  • 在我看来,当您创建一个 char 数组时,您已经在代码中声明您将一次访问每个字节。通过一次读取两个字节,您有效地破坏了通过声明数组除以字符来定义的障碍。这不是编译器问题,而更多的是可读性和样式问题。
  • 由于 char_values 彼此相邻存储,因此通过对数组进行短转换会更有效,但您的答案也很好
  • 我不同意。通过使用强制转换,您假设内存中的所有内容都正确对齐。使用按位运算符可以解决这个问题。看到这个:stackoverflow.com/questions/300808/…
  • 你又是对的,但我不是在处理 PC 代码,它是嵌入式的,我们可以完美地控制我们在内存中写入的内容;在这种情况下 char_array 位于 NVM 中,我们确保没有对齐问题,但您是绝对正确的
猜你喜欢
  • 2018-06-30
  • 2011-06-08
  • 2016-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多