为什么 'auto' 不遵守一元减号运算符?
Why does 'auto' not respect the unary minus operator?
我对 C++ 很陌生,但我发现 auto
的这种行为很奇怪:
class A{};
int main() {
A a;
auto x = -(sizeof(a));
cout << x << endl;
return 0;
}
在本例中,变量 x 是 unsigned
,尽管我在变量初始化时使用了一元减号运算符。为什么只考虑 sizeof
(std::size_t
) 的 return 类型,而不考虑由于使用运算符而存储的数字将为负数的事实?
我知道 size_t
是一个无符号整数。
我已经用 GCC 8.1.0 和 C++17 试过了。
如果我们看一下:https://en.cppreference.com/w/cpp/language/sizeof,结果的类型是 size_t
,即 unsigned
。您明确需要将其声明为 signed int
以允许负值。
您可以写 int
而不是 auto
,它允许负值。
这里的实际问题是一元减运算符的使用,就像其他内置算术运算符一样,受制于积分提升。所以令人惊讶的是,将一元减法应用于 size_t
的结果仍然是 size_t
并且没有必要责怪 auto
.
反例。在这种情况下,由于 x
的积分促销类型将为 int
,因此输出将为 -1
:
unsigned short a{1};
auto x{-a};
cout << x << endl;
(一元)-
应用于无符号值的结果是无符号的,sizeof
returns 是无符号值。
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.
The type of the result is the type of the promoted operand.
The result of sizeof
and sizeof...
is a constant of type
std::size_t
为避免实现定义的行为,您必须在应用 -
之前转换为 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.
class A{};
int main() {
A a;
auto x = -(int{sizeof(a)});
cout << x << endl;
return 0;
}
您的表达式 -(sizeof(a))
将一元运算符 -
应用于无符号类型的值。一元 - 运算符不会将无符号整数值转换为有符号整数;它而是定义了哪个无符号值将是这种操作的结果,如下所示(参见 unary arithmetic operators at 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.
因此,即使令人惊讶,auto
也可以正常工作,因为将一元 -
运算符应用于无符号值的结果仍然是无符号值。
我对 C++ 很陌生,但我发现 auto
的这种行为很奇怪:
class A{};
int main() {
A a;
auto x = -(sizeof(a));
cout << x << endl;
return 0;
}
在本例中,变量 x 是 unsigned
,尽管我在变量初始化时使用了一元减号运算符。为什么只考虑 sizeof
(std::size_t
) 的 return 类型,而不考虑由于使用运算符而存储的数字将为负数的事实?
我知道 size_t
是一个无符号整数。
我已经用 GCC 8.1.0 和 C++17 试过了。
如果我们看一下:https://en.cppreference.com/w/cpp/language/sizeof,结果的类型是 size_t
,即 unsigned
。您明确需要将其声明为 signed int
以允许负值。
您可以写 int
而不是 auto
,它允许负值。
这里的实际问题是一元减运算符的使用,就像其他内置算术运算符一样,受制于积分提升。所以令人惊讶的是,将一元减法应用于 size_t
的结果仍然是 size_t
并且没有必要责怪 auto
.
反例。在这种情况下,由于 x
的积分促销类型将为 int
,因此输出将为 -1
:
unsigned short a{1};
auto x{-a};
cout << x << endl;
(一元)-
应用于无符号值的结果是无符号的,sizeof
returns 是无符号值。
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. The type of the result is the type of the promoted operand.
The result of
sizeof
andsizeof...
is a constant of typestd::size_t
为避免实现定义的行为,您必须在应用 -
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.
class A{};
int main() {
A a;
auto x = -(int{sizeof(a)});
cout << x << endl;
return 0;
}
您的表达式 -(sizeof(a))
将一元运算符 -
应用于无符号类型的值。一元 - 运算符不会将无符号整数值转换为有符号整数;它而是定义了哪个无符号值将是这种操作的结果,如下所示(参见 unary arithmetic operators at 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.
因此,即使令人惊讶,auto
也可以正常工作,因为将一元 -
运算符应用于无符号值的结果仍然是无符号值。