int 可以别名为 unsigned int 吗?
Can an int be aliased as an unsigned int?
编译器生成的代码假设 int
可以被 unsigned int
别名化。以下代码:
int f(int& a, unsigned int& b){
a=10;
b=12;
return a;
}
int f(int& a, double& b){
a=10;
b=12;
return a;
}
使用 Clang5 生成以下程序集(类似代码由 GCC 或 ICC 生成):
f(int&, unsigned int&): # @f(int&, unsigned int&)
mov dword ptr [rdi], 10
mov dword ptr [rsi], 12
mov eax, dword ptr [rdi] #return value must be loaded since rdi might equal rsi
ret
f(int&, double&): # @f(int&, double&)
mov dword ptr [rdi], 10
movabs rax, 4622945017495814144
mov qword ptr [rsi], rax
mov eax, 10 #return value is a direct value.
ret
在上面的示例中,在第一个重载 f
中 return 值(在 eax
寄存器中)是 10 或 12 如果 b
和 a
引用同一个对象。在第二次重载中,a
和 b
不能引用同一个对象,因此 return 值始终为 10。
C++标准的这一段表达了严格的别名规则,[intro.object]/8:
[...] Two objects a and b with overlapping lifetimes that are not bit-fields may have the same address if one is nested within the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they have distinct addresses.
所以根据这个规则,一个 int
不能被一个 unsigned int
别名。
问题:
C++ 标准中是否存在允许 int
被 unsigned int
别名的例外规则?
如果不是,为什么所有编译器都假设这种可能性?
Is there an exception to this rule in the C++ standard that would allow aliasing of int by unsigned int?
是的,是 [basic.lval]/8:
If a program attempts to access the stored value of an object through
a glvalue of other than one of the following types the behavior is
undefined:
- a type that is the signed or unsigned type corresponding to the dynamic type of the object,
- a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
编译器生成的代码假设 int
可以被 unsigned int
别名化。以下代码:
int f(int& a, unsigned int& b){
a=10;
b=12;
return a;
}
int f(int& a, double& b){
a=10;
b=12;
return a;
}
使用 Clang5 生成以下程序集(类似代码由 GCC 或 ICC 生成):
f(int&, unsigned int&): # @f(int&, unsigned int&)
mov dword ptr [rdi], 10
mov dword ptr [rsi], 12
mov eax, dword ptr [rdi] #return value must be loaded since rdi might equal rsi
ret
f(int&, double&): # @f(int&, double&)
mov dword ptr [rdi], 10
movabs rax, 4622945017495814144
mov qword ptr [rsi], rax
mov eax, 10 #return value is a direct value.
ret
在上面的示例中,在第一个重载 f
中 return 值(在 eax
寄存器中)是 10 或 12 如果 b
和 a
引用同一个对象。在第二次重载中,a
和 b
不能引用同一个对象,因此 return 值始终为 10。
C++标准的这一段表达了严格的别名规则,[intro.object]/8:
[...] Two objects a and b with overlapping lifetimes that are not bit-fields may have the same address if one is nested within the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they have distinct addresses.
所以根据这个规则,一个 int
不能被一个 unsigned int
别名。
问题:
C++ 标准中是否存在允许
int
被unsigned int
别名的例外规则?如果不是,为什么所有编译器都假设这种可能性?
Is there an exception to this rule in the C++ standard that would allow aliasing of int by unsigned int?
是的,是 [basic.lval]/8:
If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:
- a type that is the signed or unsigned type corresponding to the dynamic type of the object,
- a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,