Search code examples
cpointersmallocstrict-aliasing

Can I do what I want with allocated memory


Are there limits on what I can do to allocated memory?(standard-wise)

For example

#include <stdio.h>
#include <stdlib.h>

struct str{
    long long a;
    long b;
};

int main(void) 
{
    long *x = calloc(4,sizeof(long));
    x[0] = 2;
    x[3] = 7;
//is anything beyond here legal( if you would exclude possible illegal operations)
    long long *y = x; 
    printf("%lld\n",y[0]); 
    y[0] = 2;
    memset (x,0,16);
    struct str *bar = x;
    bar->b =  4;
    printf("%lld\n",bar->a); 
    return 0;
}

To summarize:

  • Can I recast the pointer to other datatypes and structs, as long as the size fits?
  • Can I read before I write, then?
  • If not can I read after I wrote?
  • Can I use it with a struct smaller than the allocated memory?

Solution

  • Reading from y[0] violates the strict aliasing rule. You use an lvalue of type long long to read objects of effective type long.

    Assuming you omit that line; the next troublesome part is memset(x,0,16);. This answer argues that memset does not update the effective type. The standard is not clear.

    Assuming that memset leaves the effective type unchanged; the next issue is the read of bar->a.

    The C Standard is unclear on this too. Some people say that bar->a implies (*bar).a and this is a strict aliasing violation because we did not write a bar object to the location first.

    Others (including me) say that it is fine: the only lvalue used for access is bar->a; that is an lvalue of type long long, and it accesses an object of effective type long long (the one written by y[0] = 2;).

    There is a C2X working group that is working on improving the specification of strict aliasing to clarify these issues.