&引用;溢出“;关于各种C数据类型的断言:根据C标准,哪些断言保证为真?
虽然所有这些断言在我的系统上都成立,但我显然调用了一些未定义和/或特定于实现的行为。其中一些 显然不是真正的溢出 参考:这就是我问这个问题的原因&引用;溢出“;关于各种C数据类型的断言:根据C标准,哪些断言保证为真?,c,assert,integer-overflow,C,Assert,Integer Overflow,虽然所有这些断言在我的系统上都成立,但我显然调用了一些未定义和/或特定于实现的行为。其中一些 显然不是真正的溢出 参考:这就是我问这个问题的原因 num=num+1不会导致溢出num自动升级为int,然后在int中执行加法,结果为128,无溢出。然后分配执行到字符的转换 这不是溢出,但根据C 2018 6.3.1.3,会产生实现定义的结果或信号。这与溢出不同,因为C标准根本没有指定溢出时的行为,但在此代码中,它指定实现必须定义行为。-埃里克博士后 我把我认为是真实行为的东西放在评论里 因为我一直
num=num+1
不会导致溢出num
自动升级为int
,然后在int
中执行加法,结果为128,无溢出。然后分配执行到字符的转换
这不是溢出,但根据C 2018 6.3.1.3,会产生实现定义的结果或信号。这与溢出不同,因为C标准根本没有指定溢出时的行为,但在此代码中,它指定实现必须定义行为。-埃里克博士后
我把我认为是真实行为的东西放在评论里
因为我一直依赖于误解,所以我不愿意假设任何事情
#include <limits.h>
#include <assert.h>
#include <stdint.h>
#include <stddef.h>
int main(void)
{
signed char sc = CHAR_MAX;
unsigned char uc = UCHAR_MAX;
signed short ss = SHRT_MAX;
unsigned short us = USHRT_MAX;
signed int si = INT_MAX;
unsigned int ui = UINT_MAX;
signed long sl = LONG_MAX;
unsigned long ul = ULONG_MAX;
size_t zu = SIZE_MAX;
++sc;
++uc;
++ss;
++us;
++si;
++ui;
++sl;
++ul;
++zu;
assert(sc == CHAR_MIN); //integer promotion, implementation specific ?
assert(uc == 0); //integer promotion, implementation specific ?
assert(ss == SHRT_MIN); //integer promotion, implementation specific ?
assert(us == 0); //integer promotion, implementation specific ?
assert(si == INT_MIN); //overflow & undefined
assert(ui == 0); //wrap around: Guaranteed
assert(sl == LONG_MIN); //overflow & undefined ?
assert(ul == 0); //wrap around: Guaranteed ?
assert(zu == 0); //wrap around : Guaranteed ?
return (0);
}
#包括
#包括
#包括
#包括
内部主(空)
{
有符号字符sc=char_MAX;
无符号字符uc=UCHAR_MAX;
有符号短ss=SHRT_MAX;
无符号短us=USHRT_MAX;
符号整数si=整数最大值;
无符号整数ui=UINT_MAX;
有符号长sl=长_最大值;
无符号长ul=ULONG_MAX;
尺寸=最大尺寸;
++sc;
++坎特伯雷大学;
++ss;
++美国;
++si;
++用户界面;
++sl;
++ul;
++祖;
断言(sc==CHAR_MIN);//整数提升,具体实现?
断言(uc==0);//整数提升,特定于实现?
assert(ss==SHRT_MIN);//整数提升,特定于实现?
断言(us==0);//整数提升,特定于实现?
断言(si==INT_MIN);//溢出和未定义
断言(ui==0);//环绕:保证
assert(sl==LONG_MIN);//溢出和未定义?
断言(ul==0);//环绕:保证?
断言(zu==0);//环绕:保证?
返回(0);
}
各种C数据类型上的“溢出”断言:
根据C标准为True
assert(uc == 0);
assert(us == 0);
assert(ui == 0);
assert(ul == 0);
assert(zu == 0);
我认为您想测试签名字符sc=SCHAR\u MAX。。。断言(sc==SCHAR_MIN)代码>
当签名类型的范围小于int
:
作为重新分配的一部分,“结果是定义了实现或发出了定义了实现的信号”
当签名类型的范围与int
相同或更宽时:
由于++
期间有符号整数溢出而导致UB
assert(sc == CHAR_MIN); //integer promotion, implementation specific ?
各种C数据类型上的“溢出”断言:
根据C标准为True
assert(uc == 0);
assert(us == 0);
assert(ui == 0);
assert(ul == 0);
assert(zu == 0);
我认为您想测试签名字符sc=SCHAR\u MAX。。。断言(sc==SCHAR_MIN)代码>
当签名类型的范围小于int
:
作为重新分配的一部分,“结果是定义了实现或发出了定义了实现的信号”
当签名类型的范围与int
相同或更宽时:
由于++
期间有符号整数溢出而导致UB
assert(sc == CHAR_MIN); //integer promotion, implementation specific ?
取决于CHAR\u MAX+1
到CHAR
的实现定义的转换(如果CHAR
已签名);否则为false,因为CHAR\u MIN
!=<代码>SCHAR_MIN
。如果CHAR\u MAX==INT\u MAX
(可能,但不适用于满足托管实现的其他要求;请参阅),则原始sc++
是UB
assert(uc == 0); //integer promotion, implementation specific ?
永远正确
assert(ss == SHRT_MIN); //integer promotion, implementation specific ?
assert(si == INT_MIN); //overflow & undefined
assert(sl == LONG_MIN); //overflow & undefined ?
assert(zu == 0); //wrap around : Guaranteed ?
逻辑与sc
案例相同。取决于实现定义的将SHRT\u MAX+1
转换为short
,或者如果SHRT\u MAX==INT\u MAX
,则转换为UB
assert(us == 0); //integer promotion, implementation specific ?
永远正确
assert(ss == SHRT_MIN); //integer promotion, implementation specific ?
assert(si == INT_MIN); //overflow & undefined
assert(sl == LONG_MIN); //overflow & undefined ?
assert(zu == 0); //wrap around : Guaranteed ?
乌兰巴托
永远正确
assert(ss == SHRT_MIN); //integer promotion, implementation specific ?
assert(si == INT_MIN); //overflow & undefined
assert(sl == LONG_MIN); //overflow & undefined ?
assert(zu == 0); //wrap around : Guaranteed ?
乌兰巴托
永远正确
assert(ss == SHRT_MIN); //integer promotion, implementation specific ?
assert(si == INT_MIN); //overflow & undefined
assert(sl == LONG_MIN); //overflow & undefined ?
assert(zu == 0); //wrap around : Guaranteed ?
永远正确
assert(ss == SHRT_MIN); //integer promotion, implementation specific ?
assert(si == INT_MIN); //overflow & undefined
assert(sl == LONG_MIN); //overflow & undefined ?
assert(zu == 0); //wrap around : Guaranteed ?
取决于CHAR\u MAX+1
到CHAR
的实现定义的转换(如果CHAR
已签名);否则为false,因为CHAR\u MIN
!=<代码>SCHAR_MIN。如果CHAR\u MAX==INT\u MAX
(可能,但不适用于满足托管实现的其他要求;请参阅),则原始sc++
是UB
assert(uc == 0); //integer promotion, implementation specific ?
永远正确
assert(ss == SHRT_MIN); //integer promotion, implementation specific ?
assert(si == INT_MIN); //overflow & undefined
assert(sl == LONG_MIN); //overflow & undefined ?
assert(zu == 0); //wrap around : Guaranteed ?
逻辑与sc
案例相同。取决于实现定义的将SHRT\u MAX+1
转换为short
,或者如果SHRT\u MAX==INT\u MAX
,则转换为UB
assert(us == 0); //integer promotion, implementation specific ?
永远正确
assert(ss == SHRT_MIN); //integer promotion, implementation specific ?
assert(si == INT_MIN); //overflow & undefined
assert(sl == LONG_MIN); //overflow & undefined ?
assert(zu == 0); //wrap around : Guaranteed ?
乌兰巴托
永远正确
assert(ss == SHRT_MIN); //integer promotion, implementation specific ?
assert(si == INT_MIN); //overflow & undefined
assert(sl == LONG_MIN); //overflow & undefined ?
assert(zu == 0); //wrap around : Guaranteed ?
乌兰巴托
永远正确
assert(ss == SHRT_MIN); //integer promotion, implementation specific ?
assert(si == INT_MIN); //overflow & undefined
assert(sl == LONG_MIN); //overflow & undefined ?
assert(zu == 0); //wrap around : Guaranteed ?
始终正确。以下所有引用均来自C 2018,官方版本
assert(ss == SHRT_MIN); //integer promotion, implementation specific ?
assert(si == INT_MIN); //overflow & undefined
assert(sl == LONG_MIN); //overflow & undefined ?
assert(zu == 0); //wrap around : Guaranteed ?
小于int
的有符号整数,二进制+
让我们先讨论这个案例,因为正是这个案例引发了这个问题。考虑这个代码,它没有出现在以下问题:
signed char sc = SCHAR_MAX;
sc = sc + 1;
assert(sc == SCHAR_MIN);
unsigned char uc = UCHAR_MAX;
++uc;
assert(uc == 0);
6.5.6讨论二进制+
运算符。第4段说,对他们进行了调查。这导致sc+1
中的sc
被转换为int
1,并且1
已经是int
。因此,sc+1
比SCHAR_MAX
多产生一个(通常127+1=128),并且加法中没有溢出或表示问题
然后我们必须执行6.5.16.1中讨论的任务。第2段说“……右操作数的值被转换为赋值表达式的类型,并替换左操作数指定的对象中存储的值。”因此,我们必须将大于SCHAR_MAX的该值转换为带符号字符,而且它显然不能用符号字符
表示
6.3.1.3告诉我们有关整数的转换。对于这种情况,它会说“……否则,新类型将被签名,并且不能在其中表示值;要么结果是实现定义的,要么发出实现定义的信号