size_t 的否定(即 `-sizeof(struct foo)`))会发生什么?
我正在处理一些工作中的代码,其中包含以下形式的表达式
-(sizeof(struct foo))
,即 size_t
的否定,并且我不清楚 C 和 C++ 标准在看到这种情况时对编译器的要求。 具体来说,通过查看此处和其他地方,sizeof
返回一个 size_t
类型的无符号整数值。 当否定无符号整数时,我找不到任何明确的指定行为参考。 有吗?如果有,那是什么?
编辑:好的,关于无符号类型的算术有一些很好的答案,但尚不清楚实际上是否如此。 当这个否定时,它是对无符号整数进行操作,还是转换为有符号类型并用它做一些事情? 标准的预期行为是“想象它是类似大小的负数,然后对无符号值应用‘溢出’规则”吗?
I'm dealing with some code at work that includes an expression of the form
-(sizeof(struct foo))
i.e. the negation of a size_t
, and I'm unclear on what the C and C++ standards require of compilers when they see this. Specifically, from looking around here and elsewhere, sizeof
returns an unsigned integral value of type size_t
. I can't find any clear reference for specified behavior when negating an unsigned integer. Is there any, and if so, what is it?
Edit: Ok, so there are some good answers regarding arithmetic on unsigned types, but it's not clear that this is in fact such. When this negates, is it operating on an unsigned integer, or converting to a signed type and doing something with that? Is the behavior to expect from the standards "imagine it's the negative number of similar magnitude and then apply the 'overflow' rules for unsigned values"?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
来自当前 C++ 草案标准 ,第 5.3.1 节第 8 句:
因此,结果表达式仍然是无符号的,并且按照描述进行计算。
用户 @outis 在评论中提到了这一点,但我将把它放在答案中,因为 outis 没有。 如果 outis 回来并回答,我会接受。
From the current C++ draft standard, section 5.3.1 sentence 8:
So the resulting expression is still unsigned and calculated as described.
User @outis mentioned this in a comment, but I'm going to put it in an answer since outis didn't. If outis comes back and answers, I'll accept that instead.
size_t
是实现定义的无符号整数类型。对
size_t
值求反可能会得到一个size_t
类型的结果,并具有通常的无符号模行为。 例如,假设size_t
为 32 位且sizeof(struct foo) == 4
,则-sizeof(struct foo) == 4294967292
,或 232-4。除了一件事:一元
-
运算符应用整数提升 (C) 或整数提升 (C++)(它们本质上是相同的) thing) 到它的操作数。 如果size_t
至少与int
一样宽,则此提升不会执行任何操作,并且结果的类型为size_t
。 但如果int
比size_t
宽,使得INT_MAX >= SIZE_MAX
,则-
的操作数为从size_t
“升级”为int
。 在这种不太可能的情况下,-sizeof(struct foo) == -4
。如果您将该值分配回
size_t
对象,那么它将被转换回size_t
,从而生成您指定的SIZE_MAX-4
值d 期望。 但如果没有这样的转换,您可能会得到一些令人惊讶的结果。现在我从未听说过
size_t
比int
窄的实现,因此您不太可能遇到这种情况。 但这里有一个测试用例,使用unsigned Short
作为假设的窄size_t
类型的替代,它说明了潜在的问题:我的系统上的输出(有 16 -bit
short
、32 位int
和 64 位size_t
)是:size_t
is an implementation-defined unsigned integer type.Negating a
size_t
value probably gives you a result of typesize_t
with the usual unsigned modulo behavior. For example, assuming thatsize_t
is 32 bits andsizeof(struct foo) == 4
, then-sizeof(struct foo) == 4294967292
, or 232-4.Except for one thing: The unary
-
operator applies the integer promotions (C) or integral promotions (C++) (they're essentially the same thing) to its operand. Ifsize_t
is at least as wide asint
, then this promotion does nothing, and the result is of typesize_t
. But ifint
is wider thansize_t
, so thatINT_MAX >= SIZE_MAX
, then the operand of-
is "promoted" fromsize_t
toint
. In that unlikely case,-sizeof(struct foo) == -4
.If you assign that value back to a
size_t
object, then it will be converted back tosize_t
, yielding theSIZE_MAX-4
value that you'd expect. But without such a conversion, you can get some surprising results.Now I've never heard of an implementation where
size_t
is narrower thanint
, so you're not likely to run into this. But here's a test case, usingunsigned short
as a stand-in for the hypothetical narrowsize_t
type, that illustrates the potential problem:The output on my system (which has 16-bit
short
, 32-bitint
, and 64-bitsize_t
) is:ISO C 和 ISO C++ 标准都保证无符号算术以 2n 为模 - 即,对于任何上溢或下溢,它都会“回绕”。 对于 ISO C++,这是 3.9.1[basic.fundamental]/4:
对于 ISO C(99),它是 6.2.5/9:
这意味着结果保证与
SIZE_MAX - (sizeof(struct foo)) + 1 相同。
在 ISO 14882:2003 5.3.1.7 中:
Both ISO C and ISO C++ standards guarantee that unsigned arithmetic is modulo 2n - i.e., for any overflow or underflow, it "wraps around". For ISO C++, this is 3.9.1[basic.fundamental]/4:
For ISO C(99), it is 6.2.5/9:
Which means the result is guaranteed to be the same as
SIZE_MAX - (sizeof(struct foo)) + 1
.In ISO 14882:2003 5.3.1.7:
http://msdn.microsoft.com/en-我们/库/wxxx8d2t%28VS.80%29.aspx
换句话说,确切的行为将是特定于体系结构的。 如果我是你,我会避免使用这种奇怪的结构。
http://msdn.microsoft.com/en-us/library/wxxx8d2t%28VS.80%29.aspx
In other words, the exact behavior will be architecture-specific. If I were you, I would avoid using such a weird construct.
我唯一能想到的是错得我头疼……
溢出是一个功能!
The only thing I can think of is so wrong it makes my head hurt...
Overflow is a feature!
对无符号数求反对于在整个字中传播 lsb 以形成后续按位运算的掩码非常有用。
negating an unsigned number is useful for propagating the lsb across the word to form a mask for subsequent bitwise operations.