让我们看一下C / C++中的以下代码片段。
C++
// An Unsigned char example
#include
using namespace std;
void fun1()
{
unsigned char i;
for (i = 0; i < 256; i++)
cout << i << " ";
}
int main()
{
fun1();
return 0;
}
// This code is contributed by shubhamsingh10
C
// An Unsigned char example
#include
void fun1()
{
unsigned char i;
for (i = 0; i < 256; i++)
printf("%d ", i);
}
int main()
{
fun1();
return 0;
}
C++
// A signed char example
#include
using namespace std;
void fun2()
{
signed char i;
for (i = 0; i < 128; i++)
cout << i <<" ";
}
int main()
{
fun2();
return 0;
}
// This code is contributed by shubhamsingh10
C
// A signed char example
#include
void fun2()
{
signed char i;
for (i=0; i<128; i++)
printf("%d ",i);
}
int main()
{
fun2();
return 0;
}
输出:
Infinite Loop
解释:
我们知道字符变量的大小是8位或1个字节。因此,以十进制数的基数2表示,最大8位数字为11111111,这是因为8位中无符号数字的范围从0到2 8 -1
现在(11111111) 2 =(255) 10
如果将循环从0开始驱动到255,它将在循环中执行该语句256次(包括0和255)。当循环达到(255) 10时,执行完之后,变量“ i”将增加1,即执行2s补码运算,
(11111111) 2 +(00000001) 2 =(00000000) 10
注意:在这种情况下,末尾进位被丢弃;因此,最终递增的数字为0,这将导致循环的重新执行,因此循环运行了无限次。因此,如果我们将无符号字符i的限制设置为小于255而不是256,则可以避免上述情况。
现在考虑下面的程序:
C++
// A signed char example
#include
using namespace std;
void fun2()
{
signed char i;
for (i = 0; i < 128; i++)
cout << i <<" ";
}
int main()
{
fun2();
return 0;
}
// This code is contributed by shubhamsingh10
C
// A signed char example
#include
void fun2()
{
signed char i;
for (i=0; i<128; i++)
printf("%d ",i);
}
int main()
{
fun2();
return 0;
}
在GCC上的输出(标准中未定义的行为):
Infinite Loop
有符号的char范围从-2 7到2 7 -1,因此如果限制<128,它也可以无限执行。
请注意,(127) 10的2s补码为(01111111) 2加1,将得到(10000000) 2,即从2s补码形式计算出的结果为–(128) 10 。
那么如何从0循环到最大(255或128或任何其他最大限制)呢?
下面是执行此操作的一种方法。
// One way of looping till maximum of unsigned in C/C++
#include
void fun1()
{
unsigned char i = 0;
do
{
printf("%d ", i);
i++;
}
while (i > 0);
}
int main()
{
fun1();
return 0;
}
输出: 0到255之间的数字
// One way of looping till maximum of signed in C/C++
// (Same as above except first statement)
#include
void fun2()
{
signed char i = 0;
do
{
printf("%d ", i);
i++;
}
while (i > 0);
}
int main()
{
fun2();
return 0;
}
在GCC中输出: 0到127之间的数字
注意:在C语言中,带符号的溢出是未定义的行为,因此上述解决方案可能无法在所有带符号数字的机器上运行。另外,上面显示的用于签名的输出可能在所有机器上都不相同。对于无符号数字,行为已得到很好的定义。
下面在C99中提到了以下内容。
关于未签名:
涉及无符号操作数的计算永远不会溢出,因为无法用所得的无符号整数类型表示的结果的模数要比该所得的类型可以表示的最大值大一模
关于签名:
未定义行为的一个示例是整数溢出的行为。