&引用;溢出“;关于各种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告诉我们有关整数的转换。对于这种情况,它会说“……否则,新类型将被签名,并且不能在其中表示值;要么结果是实现定义的,要么发出实现定义的信号