Home>
What is strict aliasing rules and how to achieve aliasing using structures and unions?

I am studying C language by myself. This is my first question.
When investigating pointers, I discovered strict aliasing rules, and for the first time found that there are rules for aliasing objects.
I learned that the rules are: (C99)

Access to the value stored in the object must be by an lvalue that has one of the following types:

  1. Types that match the valid types of objects
  2. A modified version of the type that matches the valid type of the object
  3. Signed or unsigned type corresponding to the effective type of the object
  4. Signed or unsigned type corresponding to a modified version of the valid type of the object
    Aggregate type or union type that contains one of the types listed above among its members (including recursively contained subassemblies or members of contained unions)
  5. Character type
Error message

Of these, I understood all but the rules for structures and unions. The fourth

"Aggregate or union type containing one of the types listed above in its members (including recursively included subassemblies or members of contained unions)"

I don't know what

means and how that case is aliased.

Applicable source code

(Undefined pointer alignment is not considered this time, focusing on aliasing only.)

For example, the code is

# include<stdio.h>
# include<stdlib.h>
typedef struct s {
    double a;
    float b;
    int c;
    short d;

} st_alias;
typedef union t {
    double e;
    float f;
    int g;
    short h;
} uni_alias;

int main (void) {
    st_alias * ali_s;
    uni_alias * ali_u;
    int test_1 = 10;
    short test_2 = 22;
    double test_3 = 123.4;
    float test_4 = 222.2f;

    system ("pause");
    return 0;
}


When the state is like, the "ali_s" and "ali_u" pointers can be aliased to the four objects in the main function according to the above rules if the alignment in the transformation is correct. Does that mean you can access (change/read)? And is it realized by the member access operator (->.)?

Thank you for teaching me. Thanks for your cooperation.

Tried

In visual studio 2017 C ++, I assigned the object address to the pointer and accessed it via the pointer, but the result was not what I expected. (We have confirmed that the address did not change due to the alignment, and I don't think it is the cause.)
I also investigated whether visual studio C ++ supports strict aliasing rules, but I couldn't find any.
I thought it might not be supported in the first place.
(Since there is a situation where the definition format of the outer join of the inline function also supports the C ++ format instead of the C99 one, this may be the case ...)

Supplemental information (FW/tool version etc.)

I use visual studio C ++ 2017. (Used in .c format.)
Also, the Japanese version of strict aliasing rules is

  • Answer # 1

      

    I discovered strict aliasing rules and found out for the first time that there are rules for aliasing objects.

    The "Strict Aliasing Rules" in the C language specification is not a rule for C language programmers, but a strongrule for C language compiler makers.

    "Strict Aliasing Rules"The main theme of the C compiler is that if the variable types are different, it is possible to eliminate the possibility of aliasing each other. You can do code optimization "."Strict"is from the compiler's point of view, `` If the types are compatible,the possibility of aliasing each other should be considered'', from the programmer's point of view Comes from the nuance "Do notcreate aliaseswith incompatible types".

      

    Access to the value stored in the object must be by an lvalue that has one of the following types:
      (Omitted)

    The above five rules stipulateexceptionof the"Strict Aliasing Rules" ;. For example, the fifth "a character type" is an alias for each other because theintandchartypes are incompatible types according to the basic rules. Although it should not be, it means "It should be considered that it can be an alias (compiler perspective)" or "Alias ​​can be created (programmer perspective)" due to exceptions.


    Before you get into this subject, you need to understand the basic rules of"Strict Aliasing Rules" ;.

    void f (int * a, double * b) {
      // Since int and double types are different types, assignment to int type (* a) is ...
      * a = 0;
      // There is no need to consider the possibility of aliasing a double type (* b) variable.
      * b = 3.14;
      // In other words, it is not necessary to read the value from the memory location * a again in the following process,
      // By optimization, you can use "direct value 0 assigned in the above processing" as it is.
      printf ("% d", * a);
      // The compiler may optimize ↑ to printf ("% d", 0);or printf ("0");
    }
      

    Of these, I understood all but the rules for structures and unions. The fourth
          "Aggregate or union type containing one of the types listed above in its members (including recursively contained subassemblies or members of contained unions)"
    I don't know what the meaning of is and how the case aliasing is realized.

    The interpretation of this exception rule is as follows. From a programmer's perspective, it may seem like a natural statement.

    // Aggregate (struct) type including int type is ...
    struct S {
      double b;
      int i;
    };
    void g (struct S * s, int * a) {
      // Because it may be an alias of a type compatible with int type (including int type itself) ...
      * a = 0;
      // Memory location * a may be rewritten by the following process
      struct S t = {3.14, 42};
      * s = t;
      // In other words, in the following process, the value must be read from memory location * a.
      printf ("% d", * a);
    }

      

    I investigated whether visual studio C ++ supports strict aliasing rules, but I couldn't find it.
      I thought it might not be supported in the first place.

    Compiler support for "Strict Aliasing Rules" means "proactive code generation optimization based on type information" as described above. I don't know the latest VisualC ++ situation, but as far as I know, Visual C ++ doesn't do such aggressiveoptimization. GCC and Clang support aggressive optimization.

    If it is interpreted in good faith, it is a programmer-friendly compiler, and if it is interpreted maliciously, it is a compiler with poor optimization performance. However, there are few programs (probably) that strictly follow the"Strict Aliasing Rules" ;, and aggressive optimization is often a source of trouble. As specified in the C language specification, "the C compiler is correct and the program is wrong", but in reality, it seems that the optimization based on "Strict Aliasing Rules" is often disabled. In GCC and Clang, the-fno-strict-aliasingoption is used.

  • Answer # 2

    Hello.

    I didn't know strict aliasing rules, so when I looked around, yohhoy's article came out.
    (Translation) Understanding C/C ++ Strict Aliasing or-Why the # [email protected] ## @ ^% compiler won't let me do what I want!
    It is easy to understand.

    In short, it seems that the compiler may optimize if you do something strange, and you might delete the code entirely. (Other things may also happen. From the nose to the devil.)
    "Access to a value stored in an object must be by an lvalue that has one of the following types" does not fall under that "weird thing" according to this rule: is not it.

    uint16_t * ptr = (uint16_t *)&acopy;* ptrisacopy Because it is not compatible with, the compiler can assume thatptrdoes not point to a part ofacopy. (Although it is pointed out, it will be allowed by the rules.)
    This means that the memory pointed to by ptr can be interpreted as a memory with nowhere. It means that it is possible to judge that the operation to the memory is not affected even if it is completely deleted by optimization. Therefore, the compiler can be deleted, so there is a flow that there are compilers to delete.

    Reproduced with older compilers. There is also a warning. However, nothing newer than this was not reproduced and no warning was given. It means that not a few compilers are not deleted.

    For a

    structure, an int type pointer in the structure can point to an int type pointer, so the compiler and the destination of the structure and the int type pointer may be aliases (same area) Would have to be assumed.
    In other words, a structure that does not contain any short type and a short type pointer cannot be aliased (not in the same area), and the compiler may optimize it.

  • Answer # 3

      When

    is true, the "ali_s" and "ali_u" pointers can be aliased to the four objects in the main function according to the above rules if the alignment in the transformation is correct

    A red stranger who has nothing to do with alignment or before. Problems before strict aliasing rules. First check what union is.


    I don't know if the strict aliasing rules regarding the structure/union is a C ++ standard reading beginner,

      

    (Translation) Understand Strict Aliasing in C/C ++ Or-Why doesn't the # [email protected] ## @ ^% compiler do what I want! -yohhoy's diary
      An aggregate (struct or class) or union type can be an alias of the type it contains. (Example: When a pointer to an int is passed to a function, a pointer to a struct or union containing an int, another struct or union containing an int, or ... Can point to an int contained in a struct or union pointed to by another pointer.)

    Interpreting

    probably means the following:

    struct Hoge {
        int fuga;
    };
    int main ()
    {
        Hoge hoge;
        hoge.fuga = 2;
    }
    hogeseems to be an alias offugawhen there is a code

    . This is not so strange if you think about it. This is because a structure is accessed by a pointer after all. The operator.used for member access is a code that recognizes an offset in the address of a structure type variable at compile time from the distinguished name on the right side in many implementations, and accesses the element by pointer operation. Is output (no optimization is considered).