简体   繁体   English

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

[英]Why does 'auto' not respect the unary minus operator?

I'm quite new to C++ but I find this behaviour of auto weird: 我是很新的C ++,但我觉得这种行为auto怪异:

class A{};

int main() {
    A a;
    auto x = -(sizeof(a));
    cout << x << endl;
    return 0;
}

Variable x is unsigned in this case although I used the unary minus operator at the initialiation of the variable. 在这种情况下,变量x是unsigned ,尽管我在变量的初始化时使用了一元减运算符。 How come that only the return type of sizeof ( std::size_t ) is considered but not the fact that the stored number will be negative because of the used operator? 为什么只考虑sizeofstd::size_t )的返回类型,而不是因为使用的运算符而存储的数字是否为负数这一事实?

I'm aware of size_t being an unsigned int. 我知道size_t是一个unsigned int。

I've tried this with GCC 8.1.0 and C++17. 我用GCC 8.1.0和C ++ 17试过这个。

The actual issue here is that use of unary minus operator, just like the rest of built-in arithmetic operators, is a subject to integral promotions . 这里的实际问题是使用一元减运算符,就像其他内置算术运算符一样,是一个整体促销的主题。 So surprisingly the result of applying unary minus to size_t will be still size_t and there is no need to blame auto . 令人惊讶的是,将一元减号应用于size_t的结果仍然是size_t并且不需要责怪auto

Counter-example. 相反的例子。 In this case due to integral promotions type of x will be int so output will be -1 : 在这种情况下,由于整数提升, x类型将为int因此输出将为-1

unsigned short a{1};
auto x{-a};
cout << x << endl;

Your expression -(sizeof(a)) applies the unary - operator to a value of unsigned type. 您的表达-(sizeof(a))一元适用-操作者的无符号类型的值。 The unary - operator does not turn an unsigned integral value into a signed one; 一元运算符不会将无符号整数值转换为有符号整数值; it rather defines which unsigned value will be the result of such an operation as follows (cf. unary arithmetic operators at cppreference.com ): 它更确定哪个无符号值将是如下操作的结果(参见cppreference.com上的一元算术运算符 ):

The builtin unary minus operator calculates the negative of its promoted operand. 内置的一元减运算符计算其提升的操作数的负数。 For unsigned a, the value of -a is 2^b -a, where b is the number of bits after promotion. 对于无符号a,-a的值为2 ^ b -a,其中b是提升后的位数。

Hence, even if it may be surprising, auto works correctly, as the result of applying unary - operator to an unsigned value is still an unsigned value. 因此,即使它可能令人惊讶, auto也能正常工作,因为将unary - operator应用于无符号值仍然是无符号值。

The result of (unary) - applied to an unsigned value is unsigned, and sizeof returns an unsigned value. (一元)的结果-应用于无符号值是无符号的,而sizeof返回无符号值。

The operand of the unary - operator shall have arithmetic or unscoped enumeration type and the result is the negation of its operand. 一元运算符的操作数应具有算术或无范围的枚举类型,结果是其操作数的否定。 Integral promotion is performed on integral or enumeration operands. 对整数或枚举操作数执行整体提升。 The negative of an unsigned quantity is computed by subtracting its value from 2^n, where n is the number of bits in the promoted operand. 通过从2 ^ n减去其值来计算无符号数量的负数,其中n是提升的操作数中的位数。 The type of the result is the type of the promoted operand. 结果的类型是提升的操作数的类型。

[expr.unary.op]

The result of sizeof and sizeof... is a constant of type std​::​size_t sizeofsizeof...的结果是std​::​size_t类型的常量

[expr.sizeof]

To avoid implementation defined behaviour, you have to convert to int before applying the - 要避免实现定义的行为,您必须在应用之前转换为int -

If the destination type is signed, the value is unchanged if it can be represented in the destination type; 如果目标类型已签名,则该值如果可以在目标类型中表示,则不会更改; otherwise, the value is implementation-defined. 否则,该值是实现定义的。

[conv.integral]

class A{};

int main() {
    A a;
    auto x = -(int{sizeof(a)});
    cout << x << endl;
    return 0;
}

If we take a look at: https://en.cppreference.com/w/cpp/language/sizeof , the result is of type size_t which is unsigned . 如果我们看一下: https//en.cppreference.com/w/cpp/language/sizeof ,结果是size_t类型,它是unsigned You explicity need to declare it as an signed int to allow negative values. 您明确需要将其声明为signed int以允许负值。

Instead of auto you can write int which allows negative values. 您可以编写允许负值的int而不是auto

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM