This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Strict aliasing, int aliased with struct containing int


On 4 January 2015 at 09:22, Maxim Mikityanskiy <maxtram95@gmail.com> 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.

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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]