在溢出的情况下,i ++是否为小于int的签名类型调用未定义的行为?

chq*_*lie 7 c c++ undefined-behavior language-lawyer

很明显,由于算术溢出,以下代码调用未定义的行为:

#include <limits.h>

int test(void) {
    int i = INT_MAX;
    i++;  /* undefined behavior */
    return i;
}
Run Code Online (Sandbox Code Playgroud)

但是比小于或int等的签名类型呢?(由较小的,我假定和分别地).shortsigned charSCHAR_MAX < INT_MAXSHRT_MAX < INT_MAX

以下哪个函数调用未定义的行为,为什么?

signed char test2(void) {
    signed char i = SCHAR_MAX;
    i = i + 1;   /* implementation defined */
    return i;
}

signed char test3(void) {
    signed char i = SCHAR_MAX;
    i += 1;   /* undefined behavior or implementation defined? */
    return i;
}

signed char test4(void) {
    signed char i = SCHAR_MAX;
    i++;      /* undefined behavior or implementation defined? */
    return i;
}

signed char test5(void) {
    signed char i = SCHAR_MAX;
    ++i;      /* undefined behavior or implementation defined? */
    return i;
}
Run Code Online (Sandbox Code Playgroud)

请提供引用或引用C标准以支持您的推理.

250*_*501 1

以下代码确实会导致溢出,从而导致未定义的行为:

signed char i = SCHAR_MAX;
i++; 
Run Code Online (Sandbox Code Playgroud)

运算符后缀 ++ 不执行整数提升或通常的算术转换1。该运算符只是将操作数2的值加一。操作溢出。

一个明显的区别来自于一元算术运算符的措辞:+, -, ~,其措辞清楚地表明操作数被提升3。但对于后缀++运算符,措辞并没有说该运算符被提升为4。

显然后缀 ++ 运算符不会提升操作数。


1(引自:ISO/IEC 9899:201x 6.3.1.1 布尔值、字符和整数 2 58))
整数提升仅适用于: 作为常规算术转换的一部分、某些参数表达式、一元的操作数+、- 和 ~ 运算符,以及移位运算符的两个操作数,如其各自的子条款所指定。

2(引用自:ISO/IEC 9899:201x 6.5.2.4 后缀递增和递减运算符 2)
作为副作用,操作数对象的值会递增(即,将适当类型的值 1 添加到其中)

3 (引自:ISO/IEC 9899:201x 6.5.3.3 一元算术运算符 2)
一元 + 运算符的结果是其(提升的)操作数的值。对操作数执行整数提升,结果具有提升后的类型。

4 (引用自:ISO/IEC 9899:201x 6.5.2.4 后缀递增和递减运算符 2)
后缀 ++ 运算符的结果是操作数的值。

  • @JohannesSchaub-litb:它明确*等效*。如果你想削弱“等同”的含义,欢迎你接受所有确保的疯狂。 (2认同)
  • @2501 我在这里没有混淆任何东西。标准*明确地*指的是关于前缀和后缀递增和递减的*规范部分*中关于加法运算符和复合赋值的部分。 (2认同)
  • @2501:除非标准为短语“将适当类型的 1 添加到其中”定义了特殊含义,否则我看不到编译器编写者假设它不应该以与标准定义的向某物加 1 的其他方式(即“lvalue=lvalue+1;”和“lvalue+=1;”)。 (2认同)