Re: Strict aliasing, int aliased with struct containing int

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



At first, thanks for the reply and for the explanation! Sadly, one
thing is still not clear for me.

2015-01-04 15:15 GMT+02:00 Jonathan Wakely <jwakely.gcc@xxxxxxxxx>:
> On 4 January 2015 at 09:22, Maxim Mikityanskiy <maxtram95@xxxxxxxxx> wrote:
>> Hello!
>>
>> I'm trying to understand strict aliasing rules, and I have some
>> questions. Of course, I tried googling a lot first, but my
>> understanding contradicts with GCC behavior, so I got stucked.
>>
>> It's worth noting that I'm using GCC 4.9.2 on x86_64 and write code in
>> C. I compile it with -O3, so -fstrict-aliasing is implied.
>>
>> According to C99 (6.5/7):
>>
>>
>> An object shall have its stored value accessed only by an lvalue
>> expression that has one of the following types:
>> - a type compatible with the effective type of the object,
>> <...>
>> - an aggregate or union type that includes one of the aforementioned
>> types among its members (including, recursively, a member of a
>> subaggregate or contained union), or
>> <...>
>>
>>
>> As far as I understand this text, it's allowed to access int object
>> using pointer to struct that contains int field.
>
> I don't think your example is valid according to that text.
>
> In the expression param->value you are not accessing the object
> through the aggregate type, you are accessing it through an lvalue of
> type int, so the second bullet doesn't apply.

Hmm, it seems you are right. But if so, I'm writing object "global" of
type int using lvalue of type int, it's "a type compatible with the
effective type of the object", shouldn't the first bullet apply and 2
be stored into "global"?

> To modify the stored value through the aggregate type would be done like this:
>
>         *param = (struct aggregate){ 2 };
>
> However, that has undefined behaviour because it writes sizeof(struct
> aggregate) bytes to *param which points to an object of only
> sizeof(int) bytes. The compiler assumes that you would not write a
> program with undefined behaviour, therefore it can assume that &param
> does not alias global.
>
> If you make sizeof(struct aggregate) == sizeof(int) there is no
> undefined behaviour, and the compiler assumes that the pointer might
> alias the global.
>
> This gives the result you expect:
>
> #include <stdio.h>
>
> int global;
>
> struct aggregate {
>         int value;
> };
>
> int modify(struct aggregate *param)
> {
>         global = 1;
>         *param = (struct aggregate){ 2 };
>         return global;
> }
>
> int main()
> {
>         printf("%d\n", modify((struct aggregate *)&global));
>         return 0;
> }



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux