简体   繁体   English

指向结构的指针可以别名为无符号char数组吗?

[英]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 )编译器确实推断出显然应该允许tptra别名,但这不是标准所保证的。 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 == 0xFFF02sizeof(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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM