Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的流型溢出_C_Casting_Overflow - Fatal编程技术网

C语言中的流型溢出

C语言中的流型溢出,c,casting,overflow,C,Casting,Overflow,执行上述语句后,c有什么值 我无法解码解决这个问题的过程,提示是使用二进制加法。如果字符是8位无符号的,结果是2,即258%256 如果字符是有符号的,则结果是未定义的实现定义。简介 有两种实际情况需要考虑: char为无符号八位。因此,结果是2 char是有符号的八位字符。为此,将生成实现定义的结果或引发实现定义的信号 字符类型为无符号和八位 在这种情况下,charc=250很简单;它将c初始化为250。然后,inc+=8,该语句相当于c=c+8。在此语句中,c被提升为int,并执行加法,

执行上述语句后,
c
有什么值


我无法解码解决这个问题的过程,提示是使用二进制加法。

如果
字符是8位
无符号的
,结果是
2
,即
258%256

如果字符是有符号的
,则结果是未定义的实现定义。

简介 有两种实际情况需要考虑:

  • char
    为无符号八位。因此,结果是2
  • char
    是有符号的八位字符。为此,将生成实现定义的结果或引发实现定义的信号
字符类型为无符号和八位 在这种情况下,
charc=250很简单;它将
c
初始化为250。然后,in
c+=8
,该语句相当于
c=c+8。在此语句中,
c
被提升为
int
,并执行加法,结果是258。最后,必须将此结果转换为
char
以存储在
c

转换为无符号类型的规则是将值调整为可以表示的“比最大值多一个”。也就是说,对于最大值为255的无符号
char
,我们加上或减去256以生成一个可表示的值。所以258变成了258−256=2,并且
c
设置为2

字符类型为有符号和八位 在这种情况下,
charc=250尝试使用它无法表示的值初始化
c
。根据C 2018 6.7.9 11,初始化的执行类似于分配。根据6.5.16.1.2,赋值将值转换为左操作数的类型(左值转换后)。根据6.3.1.3,无法表示为有符号类型的值的转换由实现定义:

否则,新类型已签名,且无法在其中表示值;要么结果是实现定义的,要么引发实现定义的信号

假设执行持续超过
char c=250
c+=8,然后将8添加到
c
初始化为的任何值。这不能溢出,因为操作数升级为
int
类型,并且任何
char
值加8都可以在
int
中表示。如果加法结果可在
char
中表示,则将其存储在
c
中。否则,转换规则将再次应用:结果是实现定义的或引发实现定义的信号

假设情况 这些情况在现代实践中很少或从未发生过

如果
char
是有符号的九位,那么250是可表示的,因此
c
被初始化为250。然后,in
c+=8
,该加法产生的结果在
字符中不可表示(最大值为255),因此上述转换规则适用,结果为实现定义的结果或引发实现定义的结果

如果
char
大于9位,则不会发生错误,
c
最终为258位


如果
char
int
的宽度相同(在堆栈溢出的其他地方讨论了一种假设可能性),并且
char c=250更改为,例如,
charc=INT_MAX-5
,则
c
将被无问题地初始化,但
c+=8将在运算过程中溢出,然后行为不由C标准定义。

非常感谢Weather Vane!!此外,很明显%取的是余数值(如果我没有错的话)。那么,有没有任何可能的方法来解决使用二进制加法。如果char是有符号的,为什么结果是未定义的?希望不久能收到您的来信。@Nikhil二进制加法是
1111010+0000 1000=1 0000 0010
,模数可以看作是8位的截断,剩下的
0000 0010
是十进制的
2
@Eric Postdischil:先生,请告诉我算术溢出规则和转换规则之间的区别。C11标准草案n1570:6.3转换6.3.1算术操作数6.3.1.3有符号和无符号整数3否则,新类型是有符号的,不能在其中表示值;要么结果是实现定义的,要么引发实现定义的信号。注:实施defined@Kikky:C标准(2018和2011版本)第6.3条中的规则管理转换,即当值从一种类型更改为另一种类型时发生的转换。这样的转换会自动发生在赋值、初始化、函数调用参数和其他一些地方。算术溢出是指当算术运算的数学结果在用于算术运算的类型中不可表示时发生的情况。适用不同的规则;数学结果不会自动转换为必要的类型。假设
c
有符号,则根据c标准,溢出未定义。在许多实现中,将
c
设置为250将溢出到-6,然后添加8将使
c
2。这取决于实现。非常感谢!我仍然想问,有没有可能用二进制加法来解决这个问题?使用二进制加法的提示是250是11111010,8是1000,它们的和是100000100,也就是9位。如果
char
仅包含最后八位,则前一个1将丢失,值为00000010,因此结果为2。但是,这个提示忽略了C的规则。如果
char
是无符号的,那么这个算术的二进制视图就可以了;C的模包装规则相当于丢弃高位。如果
char
已签名,则C的规则可能与此二进制视图不同;一个实现可以做其他事情
char c = 250;
c += 8;