AVR的C代码强制转换有什么问题?


8

我定义了两个变量:

uint8_t a[2];
uint16_t b;

接下来,我想a用作类型的变量uint16_t,例如

b = (uint16_t)a;

但这是错误的!我的程序无法正确使用此类代码。当我替换buint8_t b[2]并使用元素操作时,一切都OK 。

为什么?

avr  c 

5
您为什么不在示例中添加一些值,并告诉我们您对“正确”的期望是什么,以便我们实际上可以提供帮助而无需推测您的语义意图。
vicatcu 2012年

1
这将更适合堆栈溢出。
Sharptooth 2012年

Answers:


16

a是指向字节数组的指针。如果将其强制转换为uint16_t并将其分配给b,则b它将包含SRAM中阵列基址(存储该基址)的地址。如果要将数组的两个字节a视为整数,请按照user14284的建议使用并集,但请注意,该并集将以体系结构的内存字节顺序表示字节数组(在AVR中将很小) -endian,表示字节0是最低有效字节)。用代码编写的方式是:

union{
  uint8_t a[2];
  uint16_t b;
} x;

x.b[0] = 0x35;
x.b[1] = 0x4A;

// by virtue of the above two assignments
x.a == 0x4A35 // is true

另一种不使用并集的方法是a强制转换为uint16_t指针,然后像这样取消引用:

uint8_t a[2] = {0x35, 0x4A};
uint16_t b = *((uint16_t *) a);
b == 0x4A35; // because AVR is little endian

如果使用缓冲区存储大字节序数据(例如,网络字节顺序),则需要进行字节交换以使用这两种技术。没有任何分支或临时变量的一种实现方法是:

uint8_t a[2] = {0x35, 0x4A};
a[0] ^= a[1];
a[1] ^= a[0];
a[0] ^= a[1];

a[0] == 0x4A; // true
a[1] == 0x35; // true

顺便说一下,这不是AVR,甚至不是嵌入式问题。应用级网络代码写入用于PC通常呼叫调用的函数htonlhtons(主机到网络,32位和16位的变体)和ntohlntohs它的实现是目标架构取决于是否(网络到主机,32位和16位的变体),他们是否交换字节(假设“在线”传输的字节在多字节字中时始终为大端)。


这是一个很好的答案。单独为' a' 的键是一个指针。
乔恩L

2
“另一种不使用并集的方法是将a强制转换为uint16_t指针,然后取消引用它” –实际上,这种类型的转换通常会违反严格的别名规则。除非您使用进行编译,否则不应该这样做-fno-strict-aliasing
吉姆·巴黎

3

如果打算将两个8位变量连接为一个16位变量,请使用union。如果你想投的单个成员a进入b,然后指定要使用数组的哪个元素。


2

在您的代码上,您仅转换了指向数组的指针。

您需要转换由指向的值a

b = (uint16_t)*a;

我从未使用过AVR,但是如果您使用的是16位架构,则必须确保a是字对齐的。否则可能会导致异常。


1
...这绝对不是他的意图...他希望b与a的两个元素相关(这将完全不考虑a [1]),而且在avr-gcc中可以转换的内容也没有例外或限制
vicatcu 2012年

0

的每个成员一个是8位的数字。它不能容纳更大的东西。它铸造于16位并没有做任何一个。它仅提取a可能保存的任何值,并将其转换为16位,以便在将值存储在其中时与b的格式匹配。

你甚至没有指代的成员一个。您必须使用a [0]或a [1](而不是a [2]!)。如果您单独使用a,则只需获取它的地址即可。(好抓住,布鲁诺)。

a声明为两个8位数字的数组也不会使其成为16位数字。您可以通过编程方式执行一些操作,以使用8位序列存储和检索16位值,而不是您所想的方式。


0

如果要将字节a转换为16位值,并且表示形式为little-endian(值的低8位在第一个字节中),请执行

uint16_t b = a[0] | (a[1] << 8);

对于大端表示

uint16_t b = (a[0] << 8) | a[1];

避免使用指针强制转换或联合来执行此操作,因为这会导致可移植性问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.