C语言学习笔记

1. C程序编译

C程序的编译可以简单分为4个步骤:预处理,编译,汇编,。

  • 预处理 展开头文件·删除注释,条件编译(例如#if,#ifdef),宏定义展开 (.i文件) gcc -E ex.c -o ex.i
  • 编译 检查语法,将高级语言转换成汇编语言(.s文件) gcc -S ex.i -o ex.s
  • 汇编 将汇编语言转化为机器语言(.o文件) gcc -c ex.s -o ex.o
  • 链接 链接不同系统下的库文件(可执行文件) gcc ex.o ex

2. 原码、反码、补码

2.1 基础概念

  • 数据在技术及内部是以补码的形式存储的
  • 数据分为有符号数和无符号数。
    • 正数的首位地址为0,其原码是有十进制转二进制
    • 负数的首位地址为1,其原码是十进制数转二进制数,再讲首位地址改为1。
  • 对于一个数字,技术及要使用一定的编码方式进行存储,原码、反码、补码是机器存储一个具体数字编码方式。

2.2 具体方式

原码

符号位(首位)加上真值得绝对值。

int 12的原码--->0000 0000 0000 0000 0000 0000 0000 1100(补全所有位)

int -12的原码--->1000 0000 0000 0000 0000 0000 0000 1100

反码

正数的反码与原码相同,负数的反码是除符号位,其余位取反。

int 12的反码--->0000 0000 0000 0000 0000 0000 0000 1100(补全所有位)

int -12的反码--->1111 1111 1111 1111 1111 1111 1111 0011

补码

正数的补码与原码相同,负数的补码是反码基础上加1

int 12的反码--->0000 0000 0000 0000 0000 0000 0000 1100(补全所有位)

int -12的反码--->1111 1111 1111 1111 1111 1111 1111 0100

2.3 三种编码方式各自的用处

<font size=4 color=red> 计算机只做加法运算。</font>

  • 情景1:两个正数进行运算,原码即可解决
10+2

1010 +
0010
_______________
1100----->(12)
  • 情景2:一正一负,10+(-2),
//原码
10+(-2)
 1010 +
 1010
_______________
10100----->(20)
//结果明显是不对的,那就说明负数与正数之间采用的不是原码

//反码
10+(-2)
  0000 0000 0000 0000 0000 0000 0000 1010 +
  1111 1111 1111 1111 1111 1111 1111 1110
_________________________________________
1 0000 0000 0000 0000 0000 0000 0000 1000
//我们发现,好像除去符号位的话,结果是正确的。但是有一种情况还例外
10+(-10)
 0000 0000 0000 0000 0000 0000 0000 1010 +
 1111 1111 1111 1111 1111 1111 1111 0101
_________________________________________
 1111 1111 1111 1111 1111 1111 1111 1111--->1000 0000 0000 0000 0000 0000 0000 (原码)
//除去符号位,好像结果出乎意料了啊,是-0。
//再试一下
1+(-1)

0001
1110 +
__________
1111 ----->1000(原码)
//还是-0
//虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.

//于是补码的出现, 解决了0的符号以及两个编码的问题:
1+(-1)
  0000 0000 0000 0000 0000 0000 0000 0001
  1111 1111 1111 1111 1111 1111 1111 1111 +
____________________________________________
1 0000 0000 0000 0000 0000 0000 0000 0000--->原码(0000 0000 0000 0000 0000 0000 0000 0000)
//补码
10+(-2)
  0000 0000 0000 0000 0000 0000 0000 1010 +
  1111 1111 1111 1111 1111 1111 1111 1110
_________________________________________
1 0000 0000 0000 0000 0000 0000 0000 1000
//首位的1,数据溢出了,系统自动将其舍弃了。所以结果是 1000(补码)

//1000(补码) 首位是1,说明它是正数,正数的原码,补码相同,其结果转化为十进制8。

总结:根据以上的代码,可以确定的话0的话只有+0,没有-0,所谓的0不带符号,其实就是把它包含进了正数范围去了。
这样的话,假设我们现在的int是4Byte的,那么(10000 0000 0000 0000 0000 0000 0000 0000)其实是没有反码和原码的,因为你第一位表示符号,你根本无法减1,去转换反码。
-1-int的最大值(2^31-1)的补码结果就是(10000 0000 0000 0000 0000 0000 0000 0000),因为实际上是使用以前的-0的补码来表示,所以没有反码和原码的。
(10000 0000 0000 0000 0000 0000 0000 0000)其实就是(-2^31), 所以int的最小范围就是这个,而不是((-2^31)+1)。

使用补码,不仅解决了0的问题,还能多表示一个最低数。

参考:

C++原码、反码、补码详解

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1:ndk与jni的关系 JNI概念: JNI是 java native interface ,java本地接口,...
    默默_大魔王阅读 382评论 0 1
  • 1.编译程序(1)gcc xx.c,他会默认生成一个a.out的可执行文件,在a.out所在目录,执行./a.o...
    萌面大叔2阅读 1,339评论 0 1
  • 1.编译程序 (1)gcc xx.c,他会默认生成一个a.out的可执行文件,在a.out所在目录,执行./a....
    萌面大叔2阅读 519评论 0 1
  • C语言基础 编译程序 gcc xx.c,他会默认生成a.out的可执行文件,在a.out所在目录,执行./a.ou...
    帅碧阅读 665评论 1 3
  • 撒乌耳,圣经故事里一个有污点的人物,没人愿意用的一个名字。 亡,死亡?消失? 读到100页《离别的芬芳》,了解到林...
    菩妖妖阅读 896评论 0 4