C语言DAY08 - 进制

预处理指令(代码)
###### 在我们编译之前执行的.
特点:以#号开头,编译的时候在检查语法之前,就先执行.C 文件中的预处理代码.
  • 预处理指令分类

    1. 文件包含指令

    a. 文件包含指令 #include
    b. 宏定义 #define
    c. 条件编译指令 #if

    1. 特点

    a.一般是#开头
    b.结尾没有分号
    c.在编译的时候检查语法前执行

作用:可以将指定的文件的内容拷贝到写指令的地方
  • 语法:

    include “文件路径”

    include <文件路径>

    include “/Users/aaron/Desktop/1.txt”

    1.相当于把1.txt 的内容写到这个地方
    2.然后再检查语法.要整体上没有语法错误

  • 相对路径,绝对路径

一般情况下被包含指令不会乱放,而是放在源文件目录下.和当前的.c 文件在同一个目录.方便管理.

这个时候就可以不写绝对路径而是相对路径.

- 这个时候就可以不写绝对路径而是相对路径.

#include "/Users/aaron/Desktop/1.txt"
#include "1.txt"

绝对路径:

路径从根目录开始

相对路径:

相对于当前这个文件夹的路径.和当前源文件路径相同的部分可以删除掉

尖括号和双引号
都是讲指定文件内容包含到谢指令的地方

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include

双引号尖括号
在当前源文件所在目录查找直接去编译器目录当中查找
没有就去系统自带编译器目录查找没有就报错
多文件开发
  1. 1个C程序其实就是由1个1个的函数组成的.
    当我们的程序很庞大的时候,那么程序中的函数就会很多.
    如果将这些所有的函数都写在main.c中.
    -> 混乱. 不方便管理
    -> 不利于团队开发.

  2. 每1个人负责1个模块的开发.
    程序其实都是由1个1个的模块组成的.
    模块就是1个小功能.

    微信:
    摇一摇
    朋友圈
    漂流瓶
    扫一扫
    .....
    

    不同的人负责不同的功能的开发.
    模块/功能. 函数.
    谁要使用这个功能.只需要直接调用就可以了.

  3. 如何分模块开发?

    写1个程序.
    有1个模块:做数学运算.

    1). 先新建1个.c文件.将这个功能模块的相关函数写在这个.c文件中.

    调用者这个时候,如果想要调用模块中的函数的话.就得自己先声明这些函数.
    

    2). 这样做遇到的问题.

    a. 如果写模块的人新增了1个函数,.调用者想要调用的话 就还的自己再声明.
    b. 如果写模块的人删除 1个函数 那么调用者也要自己删除函数的声明.
    c. 如果写模块的人修改了函数头 那么调用者也要跟着修改.
    

    3). 函数的声明和实现 其实都应该叫写模块的人来做.
    因为这些东西只有写模块的人自己清楚.

    所以,我们模块开发的时候,做法是这样的.
    写模块的人要提供两个文件.
    
    .h 文件 head 头文件.这个文件中专门写函数的声明.
    .c 文件 专门写函数的实现.
    
    
    如果有人想要使用这个模块中的函数.
    我只需要包含这个模块的头文件就可以了.
    
    
    这个时候.
    .h 头文件  和.c 实现文件        
    都是由写模块的人来写. 
    如果写模块的人要新增函数、修改函数、删除函数.
    要连.h文件的声明一起改.
    
    调用的人只需要包含这个.h头文件就可以了.
    
  4. 总结

    当我们的程序的函数过多的时候,就要考虑分模块开发.

    如何分模块.

    1个模块至少包含两个文件
    .h 文件 专门写函数的声明.
    .c 文件 专门写函数的实现.

进制

一种计数的方式,侧重点在于逢几进

C 语言可以识别
1. 二进制 0b
2. 八进制 0
3. 十进制
4. 十六进制 0x

int 类型变量中的值  
%d  输出10进制
%o  输出八进制不带符号
%x  输出16进制不带符号

十六进制对应
a  b  c  d  e  f
10 11 12 13 14 15
最重要的四个概念-进制转换


  • 基本概念

  1. 数码:这个数据每一位的数字是几
  2. 数位:数码在这个数当中的位置从右到左从0开始
  3. 基数:每一个数码可以用多少个数据来表示.就是它是几进制
  4. 位权

    位权 = 数码*(基数^数位)
    0的数码算出来就是0
    任何数的0次方都为1
    0b110(从右到左第二个数)
    数码:1
    数位:1
    基数:2
    位权: 1*(2^1) = 2

一.十进制转换为二进制

除二取余法.将这个数除以2(基数),直到余数为1(基数-1)或者0

    10/2    0 
5/2     1
2/2     0
1      
     对应的二进制就是1010从下往上数
二.二进制转换为十进制

加权法,将这个二进制数的每个数码的位权相加,就是对应的10进制.

10101
0位 1*(2^0) = 1
1位 0
2位 1*(2^2) = 4
3位 0
4位 1*(2^4) = 16
0b10101 = 1+4+16
三.十进制转换为八进制

除八取余

78/8 余6
9/8  余1
1
078 = 116
四.八进制转换为十进制

加权法.八进制每一个数码的位权相加

0342
0位 2*(8^0) = 2
1位 4*(8^1) = 32
2位 3*(8^2) = 192
0342 = 192+32+2 =226
五.二进制转换为八进制

三合一法则. 将低位到高位每三位分成1组 高位不够补0 每一组转换为十进制
每一次十进制连起来就是二进制对应的八进制

001 011 100 110 011
1    3   4   6   3
013463 = 0b001011100110011
六.八进制转换位二进制

一拆三.八进制的每一个数码拆乘1个三位的二进制,把这些数连起来

1   3   4   6   7   4
001 011 100 110 111 100
0134674 = 0b001011100110111100
七.二进制转换为十六进制

四合一法则

将低位到高位每4位分成1组 高位不够补0 每一组转换为16进制
每一次16进制连起来就是二进制对应的16进制

0001 1100 1010 1011 1110 1111 0101 0101
1    c    a    b    e    f    5    5
0x1cabef55 = 11100101010111110111101010101
八.十六进制转换为二进制

一拆四法则:讲这个16进制的每一位数码拆为1个4位的二进制连起来

4    d    e    a    7    6    1
0100 1101 1110 1010 0111 0110 0001
0x4dea761 = 0b100110111101010011101100001
九.八进制转换为十六进制
二进制是各进制转换的中间桥梁,先转换为二进制再转换为其他的进制.

变量存储的简单细节
  1. 内存中的数据存储单元是由一个一个的二进制位组成的
  2. 只能存储0或者1.(高电位低电位)
  3. 八个二进制位为一组,作为存储数据的最小基本单位,叫做字节
  4. 一个字节最多表示2^8=256种数据
8bit二进制位 = 1 byte字节
int 4byte
double 8byte
float 4byte
char 1byte
1.6e3 = 1.6^3(小数,负数都是错误)
sizeof 运算符

计算变量、常量在当前系统内存中占用的字节数

sizeof(数据类型) 
返回数据类型的变量在内存中占多少字节
sizeof(变量名)
变量在内存占多少字节数
sizeof(常量)
这个类型常亮在内存占多少字节.

//char 类型变量占1个,char 常量占4个

简写方法:
sizeof 10
sizeof 变量名;
sizeof 常亮;
//当判断的东西不是数据类型(int)
//可以省略小括弧
变量在内存当中会因为系统版本,编译器的区别而发生变化.sizeof 计算的是当前系统上.
原码反码补码(听懂)

    1. 无论任何数据,在内存中存储的时候都是以二进制的形式存储的.
  1. 原码,反码,补码都是二进制,只不过是二进制的不同的表现形式

> 3. 数据都是以补码的二进制存储的


    1. 一个 int 类型变量占4个字节 32位
    2. 在不考虑正负的情况可以表示2e32种数据
    3. 为了表示正负,最高位0表示整数,1表示负数
    4. 所以表示数据的只有31位.
    5. 最小值-2e31
    6. 最大值2e31-1,因为中间还有个0
    7. 原码
      最高位表示符号位,剩下的是这个数的绝对值的二进制

    10的原码
    00000000 00000000 00000000 00001010
    -8的原码
    10000000 00000000 00000000 00001000

  1. 反码

    正数的反码就是其原码
    负数的反码就是在其原码基础上,符号为不变,其他位取反
    -8的反码
    10000000 00000000 00000000 00001000
    11111111 11111111 11111111 11110111

  2. 补码

    正数的补码就是其原码.
    负数的补码就是在其反码的基础上加一
    -8的补码:
    -8的原码
    10000000 00000000 00000000 00001000
    -8的反码
    11111111 11111111 11111111 11110111
    -8的补码
    11111111 11111111 11111111 11111000

计算中只有加法没有减法,为了更加低成本的计算出结果,所以实用补码来存储数据.
3-2计算机认为是3+(-2);3加负2;
原码计算
3的原码00000000 00000000 00000000 00000011
2的原码10000000 00000000 00000000 00000010
3+(-2)10000000 00000000 000000000 00000101 
结果是一个负数,明显是不对的
实用反码计算
3的反码00000000 00000000 00000000 00000011
2的反码11111111 11111111 11111111 11111101
0     000000000 00000000 000000000 00000000
结果是0显然不对
3的补码  00000000 00000000 00000000 00000011
-2的补码 11111111 11111111 11111111 11111110
      0 00000000 000000000 00000000 00000001
      补码来运算效率最高,不需要换算
位运算
  1. 指的是1个二进制数据的每一位来参与就运算
  2. 前提是这个数必须是1个二进制
  3. 必须是补码形式
  4. 位运算的结果也是二进制的补码形式
  • 按位与:&

参与按位与的两个二进制数,如果都为1,那么结果为1,只要有一位为0,那么就是0

3 & 2
00000000 00000000 00000000 00000011
00000000 00000000 00000000 00000010
---------------------------
00000000 00000000 00000000 00000010

-3 & -4
11111111 11111111 11111111 11111100
还原成反码
11111111 11111111 11111111 11111011
10000000 00000000 00000000 00000100
任何数按位与1:看这个数最低位
如果是偶数,最低位为0,奇数为1
判断奇偶,按位与1就行了
  • 按位或. |

参与按位或的二进制数据,只要有一位为1,那么结果就为1,两位都是0才是0

3 | 2
00000000 00000000 00000000 00000011
00000000 00000000 00000000 00000010
------------------------
00000000 00000000 00000000 00000010
  • 按位取反 ~
    单目运算符.将每一位取反.

    ~3
    00000000 00000000 00000000 00000011
    11111111 11111111 11111111 11111100
    //反码
    11111111 11111111 11111111 11111011
    //补码
    10000000 00000000 00000000 00000100
    //原码

  • 按位异或: ^

相同为0 不同为1

3^2
00000000 00000000 00000000 00000011 3的补码
00000000 00000000 00000000 00000010 2的补码
--------------------------
00000000 00000000 00000000 00000001 异或后的补码
交换两个变量的值可以用异或
int a = 3;
int b = 2;

a = a ^ b; a = 1
b = a ^ b; 1 ^ 2 = 3
a = a ^ b; 1 ^ 3 = 2
1. 相同整数异或为0
2. 一个整数异或另一个整数2次结果不会变 3^2^2 =3
3. 整数相异或跟顺序无关 3^2^3 = 2^3^3 =2
  • 按位左移运算 <<

参与按位左移运算的二进制数据,向左移动指定的位数,低位不够补0,高位益处就丢弃.

3<<2
00000000 00000000 00000000 00000011
00000000 00000000 00000000 00001100
1.左移运算有可能改变其正负性
2.将一个数左移 N 位,相当于将这个数*2的 n 次方
  • 按位右移 >>

参与按位右移的二进制数据,向右移动指定的位数,低位溢出丢弃,高位补符号位

3>>2
00000000 00000000 00000000 00000011
00000000 00000000 00000000 00000000
1.右移运算不会改变正负
2.右移 n 位就等于除以2的 n 次方
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值