C中signed与unsigned

1 unsigned int i=3;
2 cout<<i * -1;

问结果是多少。

第一反应:-3。不过结果似乎不是这样的,写了个程序,运行了一下,发现是:4294967293。

1)在32位机上,int型和unsigned int型都是32位的(4个字节)。

2)enum会跟据最大值来决定类型,一般来说为int型,如果超出int型所能表示的范围,则用比int型大的最小类型来表示(unsigned int, long 或者unsigned long)

3)关于类型的大小。一般用所能表示的数据范围来比较类型的大小,如char型<unsigned char型<short型...在表达式中,一般都是由小的类型向大的类型转换(强制类型转换除外)

下面结合自己查的资料,加上自己不断地举各种情况编程,总结一下关于类型转换(仅限于算术表达式中关于整数类型的转换)的一些问题(如有缺漏,欢迎补充,感激不尽)

1、所有比int型小的数据类型(包括char,signed char,unsigned char,short,signed short,unsigned short)转换为int型。如果转换后的数据会超出int型所能表示的范围的话,则转换为unsigned int型;

2、bool型转化为int型时,false转化为0,true转换为1;反过来所有的整数类型转化为bool时,0转化为false,其它非零值都转为true;

3、如果表达式中混有unsigned short和int型时,如果int型数据可以表示所有的unsigned short型的话,则将unsigned short类型的数据转换为int型,否则,unsigned short类型及int型都转换为unsigned int类型。举个例子,在32位机上,int是32位,范围–2,147,483,648 to 2,147,483,647,unsigned short是16位,范围0 to 65,535,这样int型的足够表示unsigned short类型的数据,因此在混有这两者的运算中,unsigned short类型数据被转换为int型;

4、unsigned int 与long类型的转换规律同3,在32位机上,unsigned int是32位,范围0 to 4,294,967,295,long是32位,范围–2,147,483,648 to 2,147,483,647,可见long类型不够表示所有的unsigned int型,因此在混有unsigned int及long的表达式中,两者都被转换为unsigned long;

5、如果表达式中既有int 又有unsigned int,则所有的int数据都被转化为unsigned int类型。

经过这番总结,前面提出的问题的答案应该就很明显了吧。在表达式i*-1中,i是unsigned int型,-1是int型(常量整数的类型同enum),按第5条可以知道-1必须转换为unsigned int型,即0xffffffff,十进制的4294967295,然后再与i相乘,即4294967295*3,如果不考虑溢出的话,结果是12884901885,十六进制0x2FFFFFFFD,由于unsigned int只能表示32位,因此结果是0xfffffffd,即4294967293。

在C语言中,signed要求最高位是符号位,以下表示数据大小,而unsigned则全部位都表示大小。如果用8位二进制表示的话,signed范围就是-128到127,unsigned就是

0到255,C语言中专门用两个关键字来描述两种表示方法,于是,就产生了一些不可思议的问题。

1、溢出

  在有符号运算中可能会产生溢出问题,归纳起来就是:两个整数相加可能会溢出,两个负数相加也可能会溢出,一正一负相加肯定不会溢出。在《C深度剖析》中看到一个有趣的问题。

 1 #include <stdio.h>
 2 #include <string.h>
 3 int main(void)
 4 {
 5   char a[1000];
 6   int k = 0;
 7   for (; k < 1000; k++)
 8     {
 9       a[i] = -1-i;  
10
11   }
12   printf("%d\n", strlen(a));
13   return 0;
14 }

  最终的结果是255。因为数组a[1000]是char类型的,在C语言中明确规定char类型占一个字节内存空间,且在x86的gcc平台上 char默认是signed,一开始,k=0,a[0]=-1,随着k不断增大,当k=127,则a[127]=-128,对应的二进制是 10000000,我们知道-128是编译器能表示的最小值,当k=128,a[128]当然不可能存储-129这个值了,因为最高位发生了溢出,所以在 计算机中储存的补码值是01111111,。随着k继续增大,当k=254时,a[254]在计算机中存放的补码是00000001,而 k=255,a[255]对应的存储值是00000000,即0,strlen函数遇到第一个0就停止,所有最后的结果是k从0到254,总共长度是 255。

2、signed和unsigned混合运算

  C语言中除了char类型,编译器默认其他整型都是signed,在x86的gcc平台上包括char在内所有整型都是signed。

 1 #include <stdio.h>
 2
 3 int main(void)
 4 {
 5 unsigned a = 10;
 6 unsigned b = -10;
 7 if (a) printf("yes\n"); else printf("no\n");
 8 if (b) printf("yes\n"); else printf("no\n");
 9
10 int c = b;
11 printf("%d\n", c);
12 if (c) printf("yes\n"); else printf("no\n");
13
14 int d = -20;
15 int e = a + d;
16 printf("%d\n", e);
17 if (e) printf("yes\n"); else printf("no\n");
18
19 return 0;
20 }

最后结果是

yes
yes
-10
yes
-10
yes

  从上面例子可以看出,在C语言中,有符号数可以赋值给无符号数,结果是一个无符号数,而无符号数也可以赋值给有符号数,结果还是一个无符号数;在混合运算中,只要有一个无符号数,都会将有符号数转化成无符号数参加运算,结果也以无符号保存。

注意:signed 和 unsigned 在电脑中的存储形式是一样的,只是解释方法不同,即一个有符号,一个无符号。

%d打印的是signed类型的,而%x才是打印的unsignd类型的,用不同的打印相当于一个类型转换了。当然C++比较直观,能直接自动识别出类型并打印值。

就用上面的例子:

unsigned c = 3;
printf("%u\n",(c*(-1)));       //  打印出的是-3
printf("%u\n",(c*(-1)));       //  打印出的是4294967293
时间: 2024-08-28 07:44:31

C中signed与unsigned的相关文章

Bit operator: Left shift and Right shift (Signed or unsigned? )

No matter left shift or right shift, the result's sign should always be the same as its left operand. By default, const numbers in C/C++ is signed. -Wsign-compare { unsigned int j = 3; int k = 5; if (j == (1 << (j)));  //warning: comparison between

C语言:signed和unsigned的区别

参考博客:https://blog.csdn.net/wen381951203/article/details/79922220 signed和unsigned用于修饰整数类型(包括char,从ANSI C89标准开始支持) signed表示有符号,unsigned表示无符号.对应的有符号数的最大取值要比无符号的小约一半,因为最高一位被用来表示符号 默认的int.short.long.long long为有符号数,也就是说,int等价于signed int,short等价于signed shor

c中无符号(unsigned)和有符号(signed)两种类型。

整型的每一种都分为:无符号(unsigned)和有符号(signed)两种类型(float和double总是带符号的),在默认情况下声明的整型变量都是有符号的类型(char有点特别),如果需声明无符号类型的话就需要在类型前加上unsigned.无符号版本和有符号版本的区别就是无符号类型能保存2倍于有符号类型的正整数数据,比如16位系统中一个short能存储的数据的范围为-32768~32767,而unsigned能存储的数据范围则是0~65535.由于在计算机中,整数是以补码形式存放的.根据最高

signed和unsigned

signed:表示有符号位,最高位包括正数.负数和0: unsigned:表示无符号位,最高位表示 数值,不表示符号: signed int a:a 的取值范围是:-2^..... 这个就想不起来要占几位了.. 大学时,学了2遍编译原理,还是没有学会...悲了个催的.

转:VC中WORD,DWORD,unsigned long,unsigned short的区别(转)

typedef unsigned long       DWORD;typedef int                 BOOL;typedef unsigned char       BYTE;typedef unsigned short      WORD;typedef float               FLOAT;typedef FLOAT               *PFLOAT;typedef BOOL near           *PBOOL;typedef BOOL

verilog中signed的使用

1.在verilog中有时会用signed修饰符来修饰定义的数据,运算的时候也会用$signed()任务来强制转换数据,那么signed的修饰是为什么呢,是为了区分有符号数和无符号数的加法和乘法吗?其实不是的,因为有符号数和无符号数据的加法强结果和乘法器结构是一样的,signed的真正作用是决定如何对操作数扩位的问题. 2.verilog中的加法和乘法操作前,会先对操作数据扩位成结果相同的位宽,然后进行加法或者乘法处理.比如a/b都为4位数据,c为5位数据,c = a + b,这个运算的时候会先

C-类型转换(陷阱)

1.自动类型转换(运算符两边变量类型不同时) 1).两个变量类型自动转换成一样的类型(会根据参数类型自动转换, 而不是直接位转换), 且运算结果也是转换后的类型 2).当较低类型的数据转换为较高类型时, 一般只是形式上有所改变, 而不影响数据的实质内容, 而较高类型的数据转换为较低类型时则可能有些数据丢失 3).在进行自动类型转换的时候, 如果原来的数是无符号数, 那么在扩展的时候, 高位填充的是0, 如果是有符号数, 那么高位填充的时符号位 #include <stdio.h> int ma

C语言的补码表示和unsigned及signed的的转换

这东西实际编程时一直无视的,范围小了就换个大点的表示形式,但是总觉得基础知识还是掌握得好,免得到时候用移位运算或类型转换或笔试题时要花时间想. C语言的基本类型有char.int.float.double,另外还有说明符long.short.signed和unsigned. 首先要注意在不同操作系统中类型大小不一样,下面的情况只是考虑其中一种情况. int和char均默认为signed,二进制的最高一位来表示符号,0为正1为负. 假如short int是16位,由于第1位表示正负,所以只剩15位

misc: 2&#39;s complement, signed / unsigned number,carry flags, and overflow flags

学习汇编的过程中,一个很容易搞混的概念就是有符号数和无符号数的运算. 一个很自然的问题是,当对两个数做运算时(比如加法.减法),运算操作会因为两个符号有所不同吗?比如,我们都知道,在汇编里面,将两个数相加和相减,是这样的: addl %eax, %edxsubl %eax, %edx 那么,这两个操作会因为有符号数.无符号数的差别而有不同吗?是不是有有符号的 addl 和无符号的 addl 呢? 在这里,只讨论 加.减.乘.除 四种操作,搞明白了这个,其他的就容易懂了. 对于上面问题的回答,答案