C语言 day5 | 我的日常分享

C语言 day5

编译过程

图片

预处理:头文件包含、宏替换、条件编译、删除注释、 不做语法检查

编译:将预处理后的文件 生成 汇编文件 做语法检查

汇编:将汇编文件 编译成二进制文件

链接:将众多的二进制文件+库+启动代码 生成可执行文件

总结:更多的时候是一步到位 编译:gcc 源文件 -o 可执行文件

预处理

  1. 头文件包含 #include
  2. 宏定义 #define
  3. 条件编译 #if #endif…
  4. 一些特殊作用的预定义宏

头文件包含(了解)

#include<aaa.h> 表示从系统的指定目录下寻找aaa.h(用于包含系统的头文件)

#include"aaa.h" 表示从当前目录下寻找 如果没找到再去到系统指定目录下寻找(用于包含用户自定义的头文件)

宏定义#define

宏只在当前源文件有效
终止宏的作用范围可以用#undef N

  1. 不带参数的宏 直接替换 替换的过程叫做宏展开
  2. 带参数的宏(宏函数)
    • 格式: #define 宏名(参数1,,参数2…) 字符串(宏的参数不带类型 他不是函数只是一个宏)
    • 调用:宏名(参数)
    • 与普通函数的区别:
      • 宏函数调用多少次就展开多少次,执行代码的时候没有函数调用的过程,也不需要函数的出入栈,所以带参数的宏 浪费空间 节省时间
      • 带参数的函数 代码只有一份,存在代码段,调用的时候去代码段读取函数指令,调用的时候要压栈(保存调用函数前的相关信息),调用完出栈(恢复调用函数前的相关信息),所以函数浪费了时间 节省了空间。

案例:

1
2
3
4
5
6
7
8
9
10
11

#include<stdio.h>
#define MY_MULL(a,b) a*b
//#define MY_MULL(a,b) ((a)*(b))
int main(int argc,char *argv[]){

printf("%d",MY_MULL(10,20));//200
printf("%d",MY_MULL(10+10,20+20));//230 宏展开 本质就是宏替换
return 0;
}

案例:请计算结果

1
2
3
4
5
#define MY_ADD(a,b) a+b
#define MY_MUL(a,b) a*b

printf("%d",MY_MUL(MY_ADD(10+10,20+20),MY_MUL(10+10,20+20)));

条件编译

图片


防止头文件重复包含

方法一:每个头文件前加#pragma once 编译器决定
方法二:c/c++标准制定

1
2
3
4
5
6
7
8

#ifndef 头文件名//a.h-->__A_H__
#define 头文件名

内容

#endif

总结:
#pragma once 编译器决定 强调文件名
#ifndef c/c++标准制定 强调的宏名 而不是文件

原码 反码 补码

图片
注意:无符号数,正数 反码 原码 补码相等
重要:负数在计算机中存储的是补码(所有数据存储的都是补码只不过非负数反码、补码、原码都相同)

计算机为啥要补码?

图片
总结:

  1. 补码的意义将减法运算变加法运算
  2. 统一了0的编码
    +0 = 0000 0000=0000 0000(反码)=0000 0000(补码)
    -0 = 1000 000 = 1111 1111(反码)= 0000 0000(补码)
    图片