IS"烧焦富= 255"未定义的行为如果炭签名吗? [英] Is "char foo = 255" undefined behavior if char is signed?

查看:117
本文介绍了IS"烧焦富= 255"未定义的行为如果炭签名吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

用gcc 4.5.2 x86机器上使用Linux编译时,以下不给我任何的警告:

The following doesn't give me any warning whatsoever when compiled with gcc 4.5.2 on x86 machine with Linux:

char foo = 255;

但是当我使用 -pedantic ,GCC说:

警告:溢出隐不断转换

的方式gcc的行为是奇怪的一点点,这让我是否真正明白发生了什么事在这个作业我怀疑。我认为,如果字符是8位长的POSIX,它在默认情况下签署的,它不能持有 255

The way gcc acts is a tad strange and it makes me doubt if I really understand what's going on in this assignment. I think that if char is 8 bit long on POSIX and it's signed by default, it can't hold 255.

在C标准,它说,无符号整数溢出导致溢出,但签署整数溢出是不确定的。那么,这项任务不确定的行为?而为什么GCC这样的行为?

In C standard, it says that unsigned integer overflow results in overflow, but signed integer overflow is undefined. So is this assignment undefined behavior? And why does gcc act this way?

推荐答案

摘要:结果是实现定义的,很可能是 1 ,但它是复杂的,至少在原则上

Summary: The result is implementation-defined and very likely to be -1, but it's complicated, at least in principle.

关于溢出的规则是运营商与转换,并签署类型与无符号类型不同 - 和转换规则C90和C99之间更改

The rules regarding overflow are different for operators vs. conversions, and for signed types vs. unsigned types -- and the conversion rules changed between C90 and C99.

由于C90,有符号整数操作数(溢出,这意味着数学计算结果不能重新在EX pression的类型psented $ P $)已未定义行为操作的溢出。对于无符号整数运算,行为是明确界定为通常的环绕(严格地说标准不称之为溢出)。但你的声明:

As of C90, overflow of an operator with signed integer operands ("overflow" meaning that the mathematical result cannot be represented in the expression's type) has undefined behavior. For unsigned integer operands, the behavior is well defined as the usual wraparound (strictly speaking the standard doesn't call this an "overflow"). But your declaration:

char foo = 255;

不使用任何运营商(即 = 是一个初始化,而不是分配),所以这些方法都适用于这种情况。

doesn't use any operators (the = is an initializer, not an assignment), so none of that applies in this case.

如果键入字符可以重新present值 255 (这是可以的平淡真实字符是无符号的,或者 CHAR_BIT> = 9 ),那么当然行为是明确界定。在 INT 前pression 255 隐式转换为字符。 (因为 CHAR_BIT方式> = 8 ,这是不可能的这种特殊情况下调用无符号概括)

If type char can represent the value 255 (which is true either of plain char is unsigned or if CHAR_BIT >= 9), then of course the behavior is well defined. The int expression 255 is implicitly converted to char. (Since CHAR_BIT >= 8, it's not possible for this particular case to invoke unsigned wraparound.)

否则,转换产生不能被存储在结果的

Otherwise, the conversion yields a result that can't be stored in a char.

由于C90的,转换的结果是实现定义的 - 这意味着它保证设置来的部分的中值类型的范围字符,你能确定该值通过读取执行的文件,这是需要告诉你如何转换工作是什么。 (我从来没有见过一个实现,其中保存的值以外的任何其他 1 ,但所有的结果都是可能的原则。)

As of C90, the result of the conversion is implementation-defined -- which means that it's guaranteed to set foo to some value within the range of type char, and you can determine what that value is by reading the implementation's documentation, which is required to tell you how the conversion works. (I've never seen an implementation where the stored value is anything other than -1, but any result is possible in principle.)

C99改变了定义,因此,一个满溢转换为符号类型的或者的产生一个实现定义结果的的提出了一个实现定义的信号。

C99 changed the definition, so that an overflowing conversion to a signed type either yields an implementation-defined result or raises an implementation-defined signal.

如果编译器选择做后者,那么它必须证明其信号提高。

If a compiler chooses to do the latter, then it must document which signal is raised.

所以,如果一个实现定义的信号升高时会发生什么?该标准的第7.14节说:

So what happens if an implementation-defined signal is raised? Section 7.14 of the standard says:

一套完整的信号,它们的语义,以及它们的默认
  处理是实现定义

The complete set of signals, their semantics, and their default handling is implementation-defined

这是不完全清楚(对我)有什么可能的行为对信号的默认处理的范围。在最坏的情况下,我想这样的信号可能会终止程序。您的可能会或可能不会的能够定义捕获信号的信号处理程序。

It's not entirely clear (to me) what the range of possible behaviors for the "default handling" of signals is. In the worst case, I suppose such a signal could terminate the program. You might or might not be able to define a signal handler that catches the signal.

7.14还说:

如果当函数返回时,如果SIG的值为 SIGFPE
   SIGILL SIGSEGV ,或任何其他执行定义的值
  对应于计算异常的行为是不确定的;
  否则程序将在它的地方恢复执行
  打断了。

If and when the function returns, if the value of sig is SIGFPE, SIGILL, SIGSEGV, or any other implementation-defined value corresponding to a computational exception, the behavior is undefined; otherwise the program will resume execution at the point it was interrupted.

但我不的认为的适用,因为一个四溢的转换并不像该术语在这里用了一个计算异常。 (除非实现定义的信号恰好是 SIGFPE SIGILL SIGSEGV - 但是这将是愚蠢的)

but I don't think that applies, since an overflowing conversion is not a "computational exception" as the term is used here. (Unless the implementation-defined signal happens to be SIGFPE, SIGILL, or SIGSEGV -- but that would be silly).

所以,最后,如果一个实现选择响应于溢出转换到提高的信号时,行为(不只是结果)是至少实现定义,并且有可能是在它可能是未定义的情况。在任何情况下,似乎没有任何的移动的方式来处理这样的信号。

So ultimately, if an implementation chooses to raise a signal in response to an overflowing conversion, the behavior (not just the result) is at least implementation-defined, and there might be circumstances in which it could be undefined. In any case, there doesn't seem to be any portable way to deal with such a signal.

在实践中,我从来没有听说过发生在C99的新措词的优势的实现。因为我听说过的所有的编译器,转换的结果是实现定义的 - 并且很有可能得到你从二进制补码截断的期望。 (我并不相信,这种变化在C99是一个好主意。如果不出意外,它只要它本来会需要作出这样的回答3倍左右。)

In practice, I've never heard of an implementation that takes advantage of the new wording in C99. For all compilers I've heard of, the result of the conversion is implementation-defined -- and very probably yields what you'd expect from a 2's-complement truncation. (And I'm not at all convinced that this change in C99 was a good idea. If nothing else, it made this answer about 3 times as long as it would otherwise have needed to be.)

这篇关于IS"烧焦富= 255"未定义的行为如果炭签名吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆