C语言全面总结-3

C语言基本知识点复习-3

typedef & define

typedef 是一个C语言中的关键字 用来为一个数据类型取别名 以增加代码的可读性 用typedef定义数组、指针、结构等类型会带来很大的方便 不仅使程序书写简单 也使意义明确 增强可读性。
define 是一个C语言中的指令 不紧可以为类型取别名 还可以用于常量 变量 和开关编译等
typedef和define的区别

  1. typedef是关键字 在编译的时候起作用 会检查数据类型
    define是一个预处理指令 在预处理阶段对代码进行替换 所以宏定义不占用编译时间
  2. define没有作用域 而 type有自己的作用域
  3. 在对指针使用时有区别
    比如:
    先定义
    #define int * INT1
    typedef int * INT2
    INT1 a,b;=====>int *a,b; 表示创建了一个int型指针a和一个int 型变量b
    INT2 a,b; =====>int *a,*b; 表示创建了两个int指针a和b
    用INT1和INT2定义的a,b结果会不一样 由此可见define仅仅是做一个文字上的简单替换 而typedef不仅替换文字 同时还兼顾了替换的类型的功能

当用typedef 为结构体取别名时
正常我们定义结构体一般都是 struct + structName {…}; 这样既没有很好的可读性 而且每次创建新的结构体变量时都要写 struct +structName + structA 就很麻烦
所以用typedef为结构体取别名就很方便 例如:

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;

这样就可以直接用book来代表struct Books 这一串 既简便又增加了可读性
当然还有进阶版本 直接定义结构体+结构体指针升级套餐

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book,*bookPtr;

这个代码的意思就是为struct Books取别名为book 为struct Books *取别名为bookPtr

进程内存分布和内存管理

一般我们讲的进程内存 比如说计算机当前运行了三个进程 则对于每一个进程都会将physical memory物理内存的一部分映射成一块完整的虚拟内存 让每个进程都以为自己拥有了完整的内存空间 这样子可以极大的方便了数据和代码的组织
一个进程所映射的虚拟地址如下(virtual memory 虚拟内存)
在这里插入图片描述
上边的图中 大致把VM分成了六个大块 内核 、栈、堆、数据段、代码段、不可访问的空间 但其中内核和不可访问段是用户无法访问的
一般我们无法直接查看一个exe可执行文件的内容 但是在linux下可以使用" readelf 文件名 -s " 指令来查看一个可执行文件的section段信息
这里的一些 像11.13 .15等都对应着上图VM中不同的段位置
在这里插入图片描述

栈的全称为(run-time stack)运行时栈 意味着在运行时栈的大小是变化的 一般栈中保存的是局部变量 一旦一个函数被调用 则会创建一帧新的栈用来存放该程序的局部变量和形参 当然在实现函数的嵌套调用时 还要保存当下的代码地址和相关寄存器的值 以便于保护现场和恢复现场 但是栈的空间很小 一般只有8M
如果超出了这个界限则会产生 “栈溢出” 导致程序崩溃 所以一边进程用不宜调用太深的嵌套函数 和太多的局部变量

堆的全称为(run-time heap)运行时栈 所以堆也是大小变化的 主要用来存储用户自定的数据空间 一般有以下几个函数创建和释放
malloc() //创建一个连续的自定义空间
calloc(n,m)//创建n个每个m大小的自定义空间
realloc()//为已有的自定义空间更改大小
free()//释放自定义空间
!!! 创建动态内存空间后记得要用free释放

数据段

用来存放全局变量 静态变量 其中又分三段
.bss 用来存放未初始化静态数据 比如a[100] 这个数组没初始化 因为系统会对为初始化的静态数据自动初始化为0 但是如果直接存100个0在a[100]里有点浪费空间 所以在.bss这一段中就可以标记一下 说这个数组是未初始化的 就不用记100个0
.data 用来存放已初始化的静态变量
.rodata 顾名思义就是只读(read only data)用来存放常量

代码段

用来存放用户代码和系统代码
用户代码好理解
系统代码就是系统给可执行文件自动添加的一个“初始化代码”包括环境变量的准备 命令行参数的组织和传递 这部分数据在栈底 紧挨着内核的那里

一些细节点

  1. 栈底的那部分环境变量开始运行后就不会更改 运行过程中更改的环境变量会保存在堆中
  2. 栈和堆都是动态变化的 运行过程中 栈从上往下增长 堆从下往上增长(上边的图也可以看出来)
  3. 静态数据包括:全局变量和static修饰的局部变量
  4. 应尽量避免滥用静态变量 first 因为静态变量在整个程序运行期间都生存的 会占空间 second 例如全局变量属于共享资源 在多线程中容易产生竞争 需要小心的互斥以保护

文件I/O

I/O可以使用系统IO和标准IO
系统IO是操作系统访问文件的API 接口 例如Linux里面的open()close()
标准IO是C语言标准库中提供的结构 例如fopen()fclose()
在这里插入图片描述
当使用fopen时系统会返回文件指针int *File
open()会返回一个文件描述符 int file
一遍文件描述符会从3开始 因为0.1.2已经分别被标准输入(键盘)标准输出(显示器 )和标准出错所占据
使用文件指针或文件描述符就可以对文件进行操作了

小结

C语言基础就告一段落了 其实还有好多深入的知识点还没有复习到 比如链表结构 指针的详细 等等… 后面会继续学习计组计网 数据结构算法 和操作系统 到时候再对进阶的一些C语言知识点做进一步专门的总结归纳吧

嗜好太多 能力太小~

  • 22
    点赞
  • 126
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值