[英]Can a pointer to struct alias an unsigned char array?
#include "stdio.h"
/* array to store data receeived from CAN Bus */
unsigned char a[8] = {0xCD, 0xEF, 0x12, 0x34, 0x50, 0x00, 0x00, 0x00};
typedef struct {
unsigned int a:12;
unsigned int b:12;
unsigned int c:12;
unsigned int unused:28;
}test;
test *tptr;
int main(void)
{
tptr = (test*)( (void*)&a); // is this line braking any aliasing rule
if(tptr->a == 0xCDE)
{
printf("\n data received ok");
}
return 0;
}
I recently learned about problems due to pointer aliasing in C. I want to know if the above code is breaking any rules. 我最近了解了C语言中由于指针别名引起的问题。我想知道上面的代码是否违反了任何规则。 Could it lead to problems? 会导致问题吗?
I know that the bitfield's order is machine and implementation dependent. 我知道位域的顺序取决于机器和实现。 My question, however, is regarding pointer aliasing rules, which I want to understand more clearly 但是,我的问题是关于指针别名规则,我想更清楚地了解它。
It does break strict aliasing. 它确实破坏了严格的别名。 Some (saner) compilers do deduce that obviously tptr
should be allowed to alias a
, but this is not guaranteed by the standard. 一些(更tptr
)编译器确实推断出显然应该允许tptr
为a
别名,但这不是标准所保证的。 In fact, GCC will not consider tptr
to be aliasing a
. 事实上,GCC不会考虑tptr
被混叠a
。
Another problem is the alignment of a
. 另一个问题是的对准a
。 The x86 is quite tolerant in that regard, but many other architectures, including the ARM, are not. 在这方面,x86的容忍度很高,但包括ARM在内的许多其他体系结构却没有。
Consider (int)&a == 0xFFF02
and sizeof(int) == 4
on architecture that support fetching int
s only from addresses that are themselves multiples of sizeof(int)
. 考虑在仅支持从本身是sizeof(int)
倍数的地址中获取int
的体系结构上的(int)&a == 0xFFF02
和sizeof(int) == 4
。 Such an unaligned access would result in a bus error, if you do *(int*)&a
or even worse the program accessing the wrong location. 如果您进行*(int*)&a
甚至更糟的是程序访问错误的位置,则这种未对齐的访问将导致总线错误。
To stay clear of undefined behavior, remember that it is guaranteed that accesses through unsigned char*
are possible without alignment or aliasing constraints, not the other way round. 为了避免出现未定义的行为,请记住要确保通过unsigned char*
进行的访问无需对齐或混叠约束,而不是相反。 Thus use: 因此使用:
test buf;
can_recv((unsigned char*)&buf, sizeof buf);
if(tptr->a == 0xCDE)
{
printf("\n data received ok");
}
Another portability problem, is that you expect that bitfield to be packed a certain way. 另一个可移植性问题是您希望以某种方式打包位域。 The standard doesn't guarantee that however . 但是标准并不能保证 。 If you want portable behavior, restrict yourself to the bitfield interface ( bitfield.b1 = 1
) and don't modify the bitfied by other means. 如果您想要可移植的行为,请将自己限制在bitfield接口( bitfield.b1 = 1
)上,不要通过其他方式修改bitfied。
If portability isn't a concern, make sure to set the appropriate compiler flags that guarantee the bitfield packing you're expecting. 如果不考虑可移植性,请确保设置适当的编译器标志,以保证您期望的位域打包。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.