在溢出的情况下,i++是否对小于int的有符号类型调用未定义的行为?
Does i++ invoke undefined behavior for signed types smaller than int in case of overflow?
很明显,由于算术溢出,下面的代码调用了未定义的行为:
#include <limits.h>
int test(void) {
int i = INT_MAX;
i++; /* undefined behavior */
return i;
}
但是小于int
的符号类型,如short
或signed char
呢?(较小的,我分别假设SCHAR_MAX < INT_MAX
和SHRT_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;
}
请提供参考或引用C标准来支持你的推理。
对于+=
和类似的操作符来说,直接对目标类型的值进行操作是合乎逻辑的,在许多实现中,它们实际上就是这样做的。然而,标准要求操作符的行为就好像目标类型的值经历了任何适用的标准和平衡提升,然后处理指定的操作,然后转换回目标类型。
因此,如果s
和u
是有符号和无符号的16位变量,int
是32位,那么s*=s;
将被定义为s
的所有值[如果结果超过32767,它必须产生一个实现定义的值或引发一个实现定义的信号;大多数实现都必须自己去做除二补数缩减之外的任何事情。另一方面,u*=u;
只保证在u
的值不超过46340的情况下包装mod 65536;对于较大的值,它将调用未定义行为。
下面的代码会导致and overflow,从而导致未定义的行为:
signed char i = SCHAR_MAX;
i++;
操作符后缀++不执行整数提升或通常的算术转换1。操作符只是在操作数2的值上加1。操作溢出
一个明显的区别来自一元算术运算符的措辞:+
、-
、~
,它们的措辞清楚地表明操作数被提升为3。但是对于后缀++
操作符,措辞并没有说该操作符被提升为4。
显然后置++操作符不能提升操作数
1(引自:ISO/IEC 9899:201x 6.3.1.1布尔值、字符和整数2 58))
整数提升仅作为常规算术转换的一部分应用到certain参数表达式、一元+、-和~操作符的操作数,以及移位操作符,由它们各自的子句指定。
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)
后缀++操作符的结果是操作数的值
- 构造函数正在调用一个使用当前类类型的函数
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 从类型std::函数传递变量失败,尽管调用方期望的类型完全相同
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- C++类型特征,以查看是否可以<uint32_t>对类型"K"的任何变量调用"static_cast(k)"
- 调用外部函数,无法指定类型 C++/MVS
- 如何在另一个类中调用类型类的向量?
- 调用类型的标记构造函数(如果可用),否则为默认值
- C++ 数组和指针调用类型
- 调用类型 'const RadioMap::comp' 的对象没有匹配函数
- 如何调用类型为预定义结构的函数
- 作为模板参数的可调用类型上的C++约束
- 模板类的构造函数在使用 new 关键字时调用类型构造函数
- 在运行时之前调用类型未知的模板化函数
- 在VS2010中获取可调用类型的返回类型
- 在什么情况下会调用类型的转换运算符?
- c++-builder:转换为标准调用类型
- 没有调用类型转换操作符
- C++编译时谓词,用于测试是否可以使用 T 类型的参数调用 F 类型的可调用对象
- 没有匹配函数来调用类型 'hash<char">' 的对象(Stroustrup Book Drill)