特别地,最近我在阅读有关编译标志-fstrict-aliasing的GCC在线文档时发现了混乱的信息。它说:
-fstrict-aliasing
Allow the compiler to assume the strictest aliasing rules applicable to the language being compiled. For C (and C++), this activates optimizations based on the type of expressions. In particular, an object of one type is assumed never to reside at the same address as an object of a different type, unless the types are almost the same. For example, an
unsigned int
can alias anint
, but not avoid*
or adouble
. A character type may alias any other type. Pay special attention to code like this:
union a_union { int i; double d; }; int f() { union a_union t; t.d = 3.0; return t.i; }
The practice of reading from a different union member than the one most recently written to (called “type-punning”) is common. Even with -fstrict-aliasing, type-punning is allowed, provided the memory is accessed through the union type. So, the code above works as expected.
这是我从这个例子中理解到的和我的疑问:
1) 别名仅适用于相似类型或char类型。
由1)引起的后果: 别名 - 如其字面意思 - 是指当你有一个值和两个成员来访问它(即相同的字节)时;
疑问: 当两种类型具有相同的字节大小时,它们是否类似?如果不是,什么是类似的类型?
由1)引起的后果: 对于非相似类型(无论这意味着什么),别名不起作用;
2) 类型拆包是指我们读取与我们写入的不同成员; 它很常见,并且只要通过联合类型访问内存就可以按预期工作;
疑问: 别名是一种特殊情况的类型拆包,其中类型是相似的吗?
我感到困惑,因为它说unsigned int和double不相似,所以别名不起作用;但是在示例中,它是在int和double之间进行别名,并且明确表示它按预期工作,但称其为类型拆包: 不是因为类型是或不是相似,而是因为它正在从未写入的成员读取。但我理解别名就是为了读取未写入的成员(如其字面意思)。 我迷失了。
问题:有人可以澄清别名和类型拆包之间的区别以及两种技术的哪些用途在GCC中按预期工作?编译器标志做什么?