Week 02 复习

文章讲述了编程中的进制转换规则,如0开头表示八进制,0x/0X表示十六进制,并介绍了原码、反码和补码的概念及其转换。此外,还详细讨论了位运算符的优先级和功能,如按位与、或、异或、左移和右移。文章进一步讲解了函数的分类、使用及参数传递,并提到了递归函数的概念。最后,文章介绍了指针,一种特殊的变量类型,用于存储内存地址。
摘要由CSDN通过智能技术生成

Week 02

Day 06

进制转换

不同进制在程序的显示

  • 在C代码中,以0开头的数据表示八进制数据,以0x/0X开头的数据表示十六进制数据

    • %x 让数据以十六进制显示

    • %o 让数据以八进制显示

    • %#x %#o 显示出数据对应的进制前缀

原码,反码,补码

  • 原码:数据的二进制

  • 反码:

    • 正数的原码就是反码

    • 负数的反码:它的原码符号位不变,其他位按位取反

  • 补码:

    注意:所有数据在计算机中,都是以补码形式存储

    • 正数原码就是补码

    • 负数补码:

      1. 转换成二进制,得到原码

      2. 原码符号位不变,其余按位求反,得到反码

      3. 反码+1,得到补码

补码如何转成数据:

  • 先确定是有符号还是无符号

    1. 无符号/有符号且最高位为0,补码直接转成十进制

    2. 有符号的且最高位为1

      1. 补码-1,得到反码

      2. 符号位不变,其余为按位求反,得到原码

      3. 原码转十进制

        1111 1111 补码

        1111 1110 反码

        1000 0001 原码

        -1

位运算符

  • 单目 > 算数 > 位 > 关系 > 逻辑 > 三目 > 赋值

  • 位运算符中 ~(按位求反) 优先级最高

  • ^ 异或

  • 左边补符号位>>

  • 右移 >> 除2 左移 << 乘2

    int num = 40; printf("%d\n",num >> 1 + 2); // num>>3 //先计算1+2后 右移3 即除(2*3)6 printf("%d\n",num); // 40

& | ~ ^ << >>

  • A & B 按位相与 只有两个数的二进制同时为1,结果才为1,否则为0 (一假即假)

    1010 1110 A 0xAE

    0111 1100 B 0x7C

    ————————————

    0010 1100 C 0x2C

  • A | B 按位相或 两个数中的一个为1,结果就为1(一真即真)

    1010 1110 A 0xAE

    0111 1100 B 0x7C

    ————————————

    1111 1110 C 0xFE

  • ~A 按位取反(在位运算符中优先级最高)

    1010 1110 A 0xAE

    ————————————

    0101 0001 B 0x51

  • A ^ B 按位异或 相同为0,相异为1

    1010 1110 A 0xAE

    0111 1100 B 0x7C

    ————————————

    1101 0010 C 0xC2

  • A << n 按位左移n位,左边超出的丢弃,右边补0 相当于乘2

    1010 1110 A << 3

    1010 1110

    0111 0000

  • A >> n 按位右移n位,右边超出的丢弃,左边补符号位(遇1补1,遇0补0) 相当于除2

    1010 1110 A >>3

    1010 1110

    1111010 1

注意:只要式子中出现了位运算符,必须转换成二进制进行补码再进行运算

函数:Function

函数分类

标准库函数

  • C语言标准委员会以函数形式提供的一些基础功能,都被封装在libc.so库中,并且分在了不同的文件中,需要使用时只要把对应的头文件导入即可(例如stdio.h....) 然后通过具体的 函数名(参数) 即可完成

取随机值函数

  • srand(time(NULL)) 一定要放在循环外(前面),内部和后面都不可以

int system(const char *command);

功能:执行系统命令command

例如:清屏system("clear");

自定义函数:

函数声明: ​ 返回值类型 函数名(类型1 变量名1,类型2 变量名2,...); ​ 1、如果函数不需要参数,要写void ​ 2、如果函数没有返回值,也要写void ​ 3、如果参数类型相同,不能省略后面的类型名 ​ 隐式声明: ​ 在函数调用前没有出现函数声明或定义,那么编译器会猜测函数的返回值为int类型,如果猜对了会产生隐式声明的警告,如果没猜对会报错

函数定义:
    返回值类型 函数名(类型1 变量名1,类型2 变量名2,...)
    {
        //函数体
        return [val];
    }
函数调用:
    函数名(实参变量1,实参变量2,...);

Day 07

函数传参

  • 函数中定义的变量属于该函数,出了该函数就不能在被别的函数直接使用

  • 实参与形参(括号里的数据(int num))之间是以赋值的方式进行数据传递数据,并且是单向值传递

  • return语句其实是把返回值放入公共区域内存中(调用者和被调用者都可以访问),调用者会从该区域获取返回值;如果不写return语句,该区域会是一个随机的垃圾数据,调用者也能拿到返回值,但无意义

数组作为函数的参数

  • 数组作为函数的参数传递时,数组的长度会丢失,需要额外添加一个变量把数组长度传进去 int len

    固定搭配:
    void func(int arr[],int len);
    int arr[10];
    func(arr,10)//调用时[]不加

  • 数组作为参数传递时,时“址传递”,相当于调用者与函数共享数组

进程映像

  • 程序:存储在磁盘上的可执行文件(二进制文件,脚本文件)

  • 进程:正在系统中运行的程序

  • 进程映像:进程在内存中分布的情况

    名称中文名特点
    text代码段 (代码段+只读段 (常量) )存储的是二进制指令,常量(加'',""),权限是只读,如果强制修改会产生段错误
    data数据段初始化的全局变量,初始化为0,不算,依旧放在bss,初始化过的静态局部变量
    bss静态数据段未初始化的全局变量,在该段内存中的数据在程序开始前会自动清0,未初始化的静态局部变量
    stack栈(局部变量)局部变量和块变量,会随着程序的运行不断申请,释放(自动申请,自动释放),使用方便,由操作系统管理,缺点内存小 默认初始值是随机的
    heap该段内存由程序员手动管理,手动申请和释放,使用麻烦,优点内存足够大

局部变量和全局变量

全局变量

  • 定义在函数外的变量

    • 存储位置:data(初始化的全局变量) 或者 bss(未初始化的全局变量)

    • 生命周期:程序开始到程序结束

    • 使用范围:定义在函数外,程序的任意位置都可以使用

局部变量

  • 定义在函数内的变量

    • 存储位置:stack 栈内存

    • 生命周期:从函数开始到函数结束,自动申请,自动释放

    • 使用范围:只能在该函数范围内使用

块变量

  • 也是一种局部变量

  • 定义在if/for/while等语句块内的变量

    • 存储位置:stack 栈内存

    • 生命周期:从语句块开始到语句块结束

    • 使用范围:只能在语句块范围内使用

注意:同名的局部变量会屏蔽同名的全局变量,同名的块变量会屏蔽,同名的局部变量,同名的全局变量

因此建议:全局变量首字母大写,局部变量全部小写

类型限定符

auto

  • 用于定义自动申请,自动释放的变量(局部变量),不加就代表加了

  • 注意:在C11语法标准中用于自动识别类型

    auto int num;

    int num;

  • 注意:不能用它修饰全局变量,不能和static搭配

extern

  • 用于声明外部变量,意思是告诉编译器此变量在程序的其他地方已经定义了,先让程序通过编译,如果在链接时找不到该变量依然会报错

  • 不建议在extern时赋值,它只是声明

static

改变存储位置

  • 改变局部变量的存储位置,由stack改为data(初始化)或者bss(未初始化)

延长生命周期

  • 延长局部变量的生命周期,从程序开始直到程序结束才释放(改变了stack栈的存储位置为全局变量),同全局变量

限制作用范围

  • 使用static修饰全局变量,会限制全局变量的使用范围,限制只能在本文件内使用(不能配合extern使用)

    注意:使用static修饰全局变量,可以防止改变量被别的文件使用,以及防止命名冲突

const

  • “保护”变量的值不能被显示的修改

注意:如果通过内存进行修改,还是可以改的

注意:使用const修饰data段数据(因为数据发布靠太近了),那么该数据会存储到text段中,如果强制修改会发生段错误

volatile

  • C编译器会对普通变量的取值进行 “ 取值优化 ”,只要在使用变量的过程中该变量没有发生显式改变,那么编译器会直接使用上一次结果,而不会每次都去内存读取数据

  • 加上volatile修饰,让编译器不要对该变量进行 “ 取值优化 ”

  • 一般在驱动编程,硬件编程,多线程编程时使用

volatile int num = 10;

register

  • 存储介质:

    硬盘 < 内存 < 高级缓存 < 寄存器(register) < CPU

  • 申请把变量的存储介质由内存改为寄存器,但是由于寄存器数量有限,不一定百分百成功

注意:寄存器变量不能取地址,不安全

typedef(改变类型名称)

  • 类型重定义

  • 在定义变量前,加上typedef,那么原本的变量名就变成了这种数据类型,可以像数据类型一样定义变量

typedef int num;
num n1 = 10;
  • 常用的:uint_t time_t size_t 都是标准库用typedef重新定义出的名字

注意:它不是替换

typedef int num;  //类型重定义
​
#define num int   //替换
​
num n1;

Day 08

函数递归

  • 函数自己调用自己的行为,叫函数递归

  • 递归是分治思想的具体实现,就是把一个复杂而庞大的问题,分解成若干个相似小问题,解决小问题,从而大问题得到解决

  • 如果函数递归缺少出口设置,任意出现类似死循环的效果,且很快内存耗光程序异常结束

  • 如果能用循环循环解决的问题,不要用递归,递归会比循环更耗时耗内存

三个要素

  1. 出口 *

  2. 解决一个小问题

  3. 调用自己


Day 09

什么是指针

  • 指针是一种特殊的数据类型(eg:int char),使用它可以定义指针变量,指针变量存储的是整型数据,该数据代表了内存的编号(地址),可以通过这个编号访问到对应的内存(背)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值