int可以作为unsigned int别名吗?

时间:2018-01-02 11:34:45

标签: c++ language-lawyer strict-aliasing

编译器生成代码,假设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中,如果eaxb引用相同的值,则返回值(在a寄存器中)为10或12宾语。在第二个重载中,ab不能引用同一个对象,因此返回值始终为10.

严格别名规则由C ++标准[intro.object]/8

的这一段表示
  

[...]具有重叠生命周期的两个对象 a b 如果一个嵌套在另一个内,则可能具有相同的地址,或者如果至少有一个是零大小的基类子对象,它们的类型不同;否则,他们有不同的地址。

因此,根据此规则,int无法为unsigned int添加别名。

问题:

  1. C ++标准中的此规则是否允许int unsigned int之间的别名?

  2. 如果没有,为什么所有编译器都会假设这种可能性?

1 个答案:

答案 0 :(得分:4)

  

C ++标准中的此规则是否有例外,它允许通过unsigned int对int进行别名处理?

是的,它是[basic.lval]/8

  

如果程序试图通过访问对象的存储值   行为是除以下类型之一以外的glvalue   未定义:

     
      
  • 与对象的动态类型对应的有符号或无符号类型的类型
  •   
  • 与对象的动态类型的cv限定版本对应的有符号或无符号类型的类型,
  •