为什么'auto'不尊重一元减运算符?

Cod*_*ark 32 c++ unsigned sizeof

我对C++很新,但我发现这种auto奇怪的行为:

class A{};

int main() {
    A a;
    auto x = -(sizeof(a));
    cout << x << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

unsigned在这种情况下,变量x 虽然我在变量的初始化时使用了一元减运算符.为什么只考虑sizeof(std::size_t)的返回类型而不是因为使用的运算符而存储的数字是否为负的事实?

我知道size_t是一个unsigned int.

我用GCC 8.1.0和C++ 17试过这个.

use*_*670 28

这里的实际问题是使用一元减运算符,就像其他内置算术运算符一样,是一个整体促销的主题.令人惊讶的是,应用一元减号的结果size_t仍然是,size_t并且没有必要责备auto.

相反的例子.在这种情况下,由于积分促销类型xint如此输出将是-1:

unsigned short a{1};
auto x{-a};
cout << x << endl;
Run Code Online (Sandbox Code Playgroud)

  • 整体推广与它有什么关系?就我所见,这里没有任何东西得到宣传; `size_t` in,`size_t` out ......?!? (9认同)
  • @ acraig5075不,我的意思是令人惊讶.令人困惑的是,为什么一元减号允许首先应用于无符号类型.我的意思是一元减去应该改变值的符号,但无符号值不能改变符号. (3认同)
  • @curiousguy:基本问题是无符号类型用于两个不相交的目的:处理模运算,或者保持上限超过相应有符号类型的自然数小于2的因子.不幸的是,C不是允许程序员指定哪个是必需的,而是简单地假设"小"无符号类型应该具有后者的行为,"全尺寸"类型应该具有前者. (3认同)
  • VTT二进制减号适用于无符号值,为什么不应该一元减去? (2认同)
  • @VTT您可以将无符号整数视为正整数或模2 ^ n的整数.无符号无符号的否定仅在模运算(Z /(2 ^ n)Z)方面有意义.但是说一些字节是一个整数模数是荒谬的,它是一个正数. (2认同)

Ste*_*ner 22

表达式-(sizeof(a))将一元运算-符应用于无符号类型的值.一元运算符不会将无符号整数值转换为有符号整数值; 它更确定哪个无符号值将是如下操作的结果(参见cppreference.com上的一元算术运算符):

内置的一元减运算符计算其提升的操作数的负数.对于无符号a,-a的值为2 ^ b -a,其中b是提升后的位数.

因此,即使它可能令人惊讶,也能auto正常工作,因为将一元运算-符应用于无符号值仍然是无符号值.

  • "_operator不会将无符号整数值转换为带符号的整数值"如果你使用无符号进行模数运算就完全可以理解,如果你对自然数使用unsigned,那就没有任何意义 (4认同)

Cal*_*eth 5

-应用于无符号值的(一元)结果为无符号,并sizeof返回无符号值。

一元运算符的操作数应具有算术或无作用域的枚举类型,其结果是其操作数的取反。积分提升是对整数或枚举操作数执行的。无符号数量的负数是通过从2 ^ n中减去其值来计算的,其中n是提升操作数中的位数。结果的类型是提升操作数的类型。

[expr.unary.op]

的结果sizeofsizeof...类型为一个恒定 std?::?size_­t

[expr.sizeof]

为避免实现定义的行为,您必须先转换为,int然后再应用-

如果目标类型是带符号的,则该值可以在目标类型中表示,则该值保持不变。否则,该值是实现定义的。

[conv.integral]

class A{};

int main() {
    A a;
    auto x = -(int{sizeof(a)});
    cout << x << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)