[英]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;
}
我最近了解了C語言中由於指針別名引起的問題。我想知道上面的代碼是否違反了任何規則。 會導致問題嗎?
我知道位域的順序取決於機器和實現。 但是,我的問題是關於指針別名規則,我想更清楚地了解它。
它確實破壞了嚴格的別名。 一些(更tptr
)編譯器確實推斷出顯然應該允許tptr
為a
別名,但這不是標准所保證的。 事實上,GCC不會考慮tptr
被混疊a
。
另一個問題是的對准a
。 在這方面,x86的容忍度很高,但包括ARM在內的許多其他體系結構卻沒有。
考慮在僅支持從本身是sizeof(int)
倍數的地址中獲取int
的體系結構上的(int)&a == 0xFFF02
和sizeof(int) == 4
。 如果您進行*(int*)&a
甚至更糟的是程序訪問錯誤的位置,則這種未對齊的訪問將導致總線錯誤。
為了避免出現未定義的行為,請記住要確保通過unsigned char*
進行的訪問無需對齊或混疊約束,而不是相反。 因此使用:
test buf;
can_recv((unsigned char*)&buf, sizeof buf);
if(tptr->a == 0xCDE)
{
printf("\n data received ok");
}
另一個可移植性問題是您希望以某種方式打包位域。 但是標准並不能保證 。 如果您想要可移植的行為,請將自己限制在bitfield接口( bitfield.b1 = 1
)上,不要通過其他方式修改bitfied。
如果不考慮可移植性,請確保設置適當的編譯器標志,以保證您期望的位域打包。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.