Page 39 - C-Language
P. 39

int* b = a.i;
             *b = 2;

             _Thread_local bufType a = { .c = { 0 } };
             int* b = a.i;
             *b = 3;
         }


        Here, the union ensures that the compiler knows from the start that the buffer could be accessed
        through different views. This also has the advantage that now the buffer has a "view" a.i that
        already is of type int and no pointer conversion is needed.

        Effective type


        The effective type of a data object is the last type information that was associated with it, if any.


         // a normal variable, effective type uint32_t, and this type never changes
         uint32_t a = 0.0;

         // effective type of *pa is uint32_t, too, simply
         // because *pa is the object a
         uint32_t* pa = &a;

         // the object pointed to by q has no effective type, yet
         void* q = malloc(sizeof uint32_t);
         // the object pointed to by q still has no effective type,
         // because nobody has written to it
         uint32_t* qb = q;
         // *qb now has effective type uint32_t because a uint32_t value was written
         *qb = 37;

         // the object pointed to by r has no effective type, yet, although
         // it is initialized
         void* r = calloc(1, sizeof uint32_t);
         // the object pointed to by r still has no effective type,
         // because nobody has written to or read from it
         uint32_t* rc = r;
         // *rc now has effective type uint32_t because a value is read
         // from it with that type. The read operation is valid because we used calloc.
         // Now the object pointed to by r (which is the same as *rc) has
         // gained an effective type, although we didn't change its value.
         uint32_t c = *rc;

         // the object pointed to by s has no effective type, yet.
         void* s = malloc(sizeof uint32_t);
         // the object pointed to by s now has effective type uint32_t
         // because an uint32_t value is copied into it.
         memcpy(s, r, sizeof uint32_t);


        Observe that for the latter, it was not necessary that we even have an uint32_t* pointer to that
        object. The fact that we have copied another uint32_t object is sufficient.


        Violating the strict aliasing rules


        In the following code let us assume for simplicity that float and uint32_t have the same size.




        https://riptutorial.com/                                                                               15
   34   35   36   37   38   39   40   41   42   43   44