I didn't realize the code violated strict aliasing. After reading it,
it seems trivial. Somehow I also thought this is only a C++ thing.
Apparently this is "defined as undefined behavior" in C99?

Thanks a lot! You just found a bug in my code.

Regards,
Thanks,
Hendrik Greving

On Wed, Oct 2, 2013 at 3:19 AM, Mikael Pettersson <mikpeli...@gmail.com> wrote:
> Hendrik Greving writes:
>  > gcc --version
>  > gcc (GCC) 4.8.1
>  >
>  > (4.7.2 seems to work)
>  >
>  > gcc -g -fPIC -O2 -Wall -o test test.c
>  >
>  > ./test
>  > type_a is 0x0
>  >
>  > Correct would be 0x14000. I don't see how the C-code could be
>  > ambiguous, I think this is a bug?
>  >
>  > test.c:
>  >
>  > #include <stdio.h>
>  >
>  > typedef struct
>  > {
>  >     unsigned int a:4;
>  >     unsigned int b:5;
>  >     unsigned int c:5;
>  >     unsigned int d:18;
>  > } my_comb_t;
>  >
>  > struct my_s
>  > {
>  >     int l;
>  > };
>  >
>  > my_comb_t *getps_f (struct my_s *a);
>  >
>  > #define GETPS(x) getps_f(&(x))
>  >
>  > my_comb_t *
>  > getps_f (struct my_s *a)
>  > {
>  >   my_comb_t *p = (my_comb_t *) &(a->l);
>  >   return p;
>
> This is where the test case is wrong.  You need to use a union so that
> gcc can see the type punning, or compile with -fno-strict-aliasing.
>
> Without -fno-strict-aliasing I see different results for -m32 vs -m64,
> but not across gcc versions; with -fno-strict-aliasing all results match.
>
>  > }
>  >
>  > int g_modes = 5;
>  >
>  > int main(void)
>  > {
>  >     int modes = g_modes;
>  >     int type_a = 0;
>  >
>  >     if (modes)
>  >     {
>  >         struct my_s m;
>  >         m.l = type_a;
>  >         my_comb_t *p = GETPS(m);
>  >         p->d |= modes;
>  >         type_a = m.l;
>  >     }
>  >     printf("type_a is 0x%x\n", type_a);
>  >     return 0;
>  > }

Reply via email to