Is it legal to alias a char array through a pointer to int?

后端 未结 3 2572
别跟我提以往
别跟我提以往 2021-02-20 17:57

I know that the following is explicitly allowed in the standard:

int n = 0;
char *ptr = (char *) &n;
cout << *ptr;

What about this?

相关标签:
3条回答
  • 2021-02-20 18:34

    The code int *ptr = (int *) &storage[0]; *ptr = 0; causes undefined behaviour by violating the strict aliasing rule (C++14 [basic.lval]/10)

    The objects being accessed have type char but the glvalue used for the access has type int.

    The "dynamic type of the object" for a char is still char. (The dynamic type only differs from the static type in the case of a derived class). C++ does not have any equivalent of C's "effective type" either, which allows typed objects to be "created" by using the assignment operator into malloc'd space.


    Regarding correct use of std::aligned_storage, you're supposed to then use placement-new to create an object in the storage. The use of placement-new is considered to end the lifetime of the char (or whatever) objects, and create a new object (of dynamic storage duration) of the specified type, re-using the same storage. Then there will be no strict aliasing violation.

    You could do the same thing with the char array, e.g.:

    alignas(int) char storage[sizeof(int)];
    int *ptr = new(storage) int;
    *ptr = 0;
    cout << *ptr;
    

    Note that no pseudo-destructor call or delete is required for built-in type int. You would need to do that if using a class type with non-trivial initialization. Link to further reading

    0 讨论(0)
  • 2021-02-20 18:49
    *ptr = 0;
    

    writes to an int, so it is an access to int, with an lvalue of type int, so that part of the code is fine.

    The cast is morally fine, but the C/C++ standard texts don't clearly describe casts, or pointers, or anything fundamental.

    0 讨论(0)
  • 2021-02-20 18:54

    The union construct might be useful here.

    union is similar to struct, except that all of the elements of a union occupy the same area of storage.

    They are, in other words, "different ways to view the same thing," just like FORTRAN's EQUIVALENCE declaration. Thus, for instance:

    union {
      int   foo;
      float bar;
      char  bletch[8];
    }
    

    offers three entirely-different ways to consider the same area of storage. (The storage-size of a union is the size of its longest component.) foo, bar, and bletch are all synonyms for the same storage.

    union is often used with typedef, as illustrated in this StackOverflow article: C: typedef union.

    0 讨论(0)
提交回复
热议问题