为什么我们要在C中取消对int类型进行签名和签名? [英] Why Do We have unsigned and signed int type in C?

查看:184
本文介绍了为什么我们要在C中取消对int类型进行签名和签名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是C语言的初学者.我最近了解了2's Complement和其他表示负数的方法,以及为什么2's complement是最合适的.

I am a beginner in C . I have recently learned about 2's Complement and other ways to represent negative number and why 2's complement was the most appropriate one.

例如,我想问的是

int a = -3;
unsigned int b = -3; //This is the interesting Part.

现在,用于转换int类型

Now , for the conversion of int type

标准说:

6.3.1.3有符号和无符号整数

6.3.1.3 Signed and unsigned integers

将具有整数类型的值转换为_Bool以外的其他整数类型时,如果 可以用新类型表示该值,该值不变.

When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.

否则,如果新类型是无符号的,则通过重复加或 比新类型可以表示的最大值多减去一个 直到该值在新类型的范围内.

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

第一段不能使用,因为-3不能用unsigned int表示.

The first paragraph can't be used as -3 can't be represented by unsigned int.

因此第2款开始起作用,我们需要知道unsigned int的最大值.可以在 limits.h 中找到 UINT_MAX .在这种情况下,最大值为4294967295,因此计算公式为:

Therefore paragraph 2 comes to play and we need to know the maximum value for unsigned int. It can be found as UINT_MAX in limits.h. The maximum value in this case is 4294967295 so the calculation is:

-3 + UINT_MAX + 1 = -3 + 4294967295 + 1 = 4294967293  

现在二进制中的429496729311111111 11111111 11111111 11111101,而2的补数形式的-311111111 11111111 11111111 11111101,因此它们本质上是相同的位表示形式,无论我尝试分配给无符号的哪个负整数,它始终是相同的int.unsigned unsigned type不是多余的.

Now 4294967293 in binary is 11111111 11111111 11111111 11111101 and -3 in 2's Complement form is 11111111 11111111 11111111 11111101 so they are essentially same bit representation , it would be always same no matter what negative integer i am trying to assign to unsigned int.So isn't unsigned type redundant.

现在我知道printf("%d" , b)是根据标准的未定义行为,但不是那是一种合理且更直观的处理方式.如果将负数表示为2's Complement,这将是相同的,这就是我们现在所拥有的,并且使用其他方式的情况很少,并且很可能不会在未来的发展中出现.

Now i know that printf("%d" , b) is an undefined behavior according to standard, but isn't that what is a reasonable and more intuitive way to do things. As representation will be same if negative are represented as 2's Complement and that is what we have now , and other ways used are rare and most probably will not be in future developments.

所以如果我们只能用一种类型说int,那么现在如果int x = -1然后%d检查符号位,并且如果符号位为1并且%u始终解释纯二进制数字,则打印负数(位).由于使用2's complement,已经处理了加法和减法.因此,这种更直观,更简单的做事方式也并非如此.

So if we could have only one type say int , now if int x = -1 then %d checks for the sign bit and print negative number if sign bit is 1 and %ualways interpret the plain binary digit (bits) as it is . Addition and subtraction are already dealt with because of using 2's complement. So isn't this more intuitive and less complex way to do things.

推荐答案

同时具有输入,输出和计算功能非常方便.例如,比较和除法分为有符号和无符号变体(顺便说一句,无符号和2的补码有符号类型在位级别的乘法是相同的,就像加法和减法一样,并且两者都可以编译为CPU的同一乘法指令).此外,在发生溢出(除以零的情况除外)的情况下,未签名的操作不会引起不确定的行为,而有符号的操作则会导致未定义的行为.总体而言,无符号算术定义良好,无符号类型具有单一表示形式(与带符号类型的三种不同)不同,尽管实际上,如今只有一种.

It's handy to have both for input, output and computation. For example, comparison and division come in signed and unsigned varieties (btw, at the bit level multiplication is the same for unsigned and 2's complement signed types, just like addition and subtraction and both may compile into the same multiplication instruction of the CPU). Further, unsigned operations do not cause undefined behavior in case of overflow (except for division by zero), while signed operations do. Overall, unsigned arithmetic is well defined and unsigned types have a single representation (unlike three different ones for signed types, although, these days in practice there's just one).

有一个有趣的转折.现代C/C ++编译器利用以下事实:有符号的溢出会导致未定义的行为.逻辑是它永远不会发生,因此可以进行一些其他优化.如果确实发生这种情况,则标准会说这是未定义的行为,并且您的越野车程序在法律上被搞砸了.这意味着您应该避免签名溢出和所有其他形式的UB.但是,有时您可以仔细地编写永远不会导致UB的代码,但是使用有符号算术比使用无符号算术更有效.

There's an interesting twist. Modern C/C++ compilers exploit the fact that signed overflows result in undefined behavior. The logic is that it never happens and therefore some additional optimizations can be done. If it actually happens, the standard says it's undefined behavior, and your buggy program is legally screwed. What this means is that you should avoid signed overflows and all other forms of UB. However, sometimes you can carefully write code that never results in UB, but is a bit more efficient with signed arithmetic than with unsigned.

请研究未定义,未指定和实现定义的行为.它们都在附件之一(J?)的标准末尾列出.

Please study the undefined, the unspecified and the implementation-defined behaviors. They are all listed at the end of the standard in one of the annexes (J?).

这篇关于为什么我们要在C中取消对int类型进行签名和签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆