无符号和有符号

在C语言里,整数的表示有有符号无符号两种

无符号 有符号 32位 64位
unsigned char char 1 1
unsigned short short 2 2
unsigned int int 4 4
unsigned long long 4 8
unsigned long long long long 8 8

无符号是用原码表示,有符号使用补码表示,那么他们的加,减,乘,积,取反是否有区别呢?

测试代码

#include <stdio.h>
int main()
{
	int a = 10 , b= 10;
	unsigned c = 10, d= 10;
	a = a+b;
	c = c+d;
}

unsigned int无符号和int有符号的加法,乘法和取反
无符号加法和有符号加法都是使用使用 add指令,我感觉应该很清晰

#include <stdio.h>
int main()
{
	int a = 10 , b= 10;
	unsigned c = 10, d= 10;
	a = a-b;
	c = c-d;
}

unsigned int无符号和int有符号的加法,乘法和取反

无符号加法和有符号减法都是使用使用 sub指令,我感觉也应该很清晰,毕竟补码的作用就是把原来减法运算统一成加法运算,所以本质上sub指令和add指令是一样的

测试代码:

#include <stdio.h>
int main()
{
	int a = 10,b = 10;
	unsigned c = 10,d = 10;
	a *=b;
	c*=d;
}

unsigned int无符号和int有符号的加法,乘法和取反

通过反汇编之后,发现无论是有符号int,还是无符号unsigned int,使用的都是无符号乘法指令imul。
所以无符号乘法和有符号乘法都是一样的(后面证明)
那为什么指令集系统里要用imul(无符号乘法)和mul(有符号乘法)呢?
经过Google发现:imul和mul的确是一样的,唯一的区别是执行完后对标志位flags中CF和OF设置。但是标志位是我们不care的。
实在想知道的:可以看下边ORACLE 提供的IA-32 汇编语言参考手册中imul和mul对标志位flags的影响
ORACLE imul指令
ORACLE mul指令

取反

#include <stdio.h>
int main()
{
	int a = 10;
	unsigned c = 10;
	a = -a;
	c = -c;
}

unsigned int无符号和int有符号的加法,乘法和取反
可能会有质疑:无符号求反,好像是UB,的确,无符号求反在GCC上可以通过编译,但是在visual studio上报错。但是本文是对于csapp里的总结,所以就当学知识了。

ref
CSAPP

ORACLE imul
ORACLE mul
x86汇编当中imull 和 mull 区别

相关文章: