跳至主要內容

知识点总结

村雨遥原创大约 7 分钟C 语言教程C

知识点总结

共勉

不要哀求,学会争取。若是如此,终有所获。

Debug 和 Release 版本比较

  • Debug 附加了许多调试信息,主要用于调试,故文件大;
  • Release 是经过优化后的版本,去掉了调试信息,代码进行了优化,故文件较小,且编译速度快过 Debug,用于发布平台的配置管理器的设置;

32 位与 64 位

  • 32 位,地址为 32 位,最大使用内存 4G,只能运行 32 位的数据;
  • 64 位,地址为 64 位,既可以运行 32 位的数据,也可以运行 64 位的数据;

指针

  • 指针是个量,对应一块内存区域;
  • 指针存储的是某个内存单元的地址;
  • 访问方式:

1、直接访问:按变量地址存取变量值,取地址符&;

2、间接访问:通过存放变量地址的变量去访问变量,间接运算符*;

  • 在函数中改变一个外部变量,需要变量的地址;
  • 若是数据,需要指向数据的指针存储数据的地址;
  • 若是指针,需要指向指针的指针存用户指针的地址;

数组与指针

  • p[i]等价于*(p+i),&p[i]等价于 p+i;
  • a[i][j]等价于*(*(a+i)+j),&a[i][j]等价于*(a+i)+j, a[i]等价于*(a+i);
  • 行数组指针定义方法:数据类型(*指针变量名)[二维数组列数];
  • 二维数组地址不可变化,数据可以变化,可以在不修改地址的情况下管理数据,指针数组指向的数据不可变化,但地址可以变化,在不修改数据的情况下查看数据;
  • 三维数组与指针,A[i][j][k]的三种表达形式:*(A[i][j]+k)、*(*(A[i]+j)+k)、*(*(*(A+i)+j)+k);

函数与指针

  • 若在程序中定义了一个函数,在编译时,编译系统为函数代码分配一段存储空间,这段存储空间的起始地址,称为这个函数的指针,int(*p)(int, int),代表定义 p 是指向函数的指针变量,可以指向类型为整形且有两个整形参数的函数;
  • 定义返回值为指针值的函数的一般形式:类型名 *函数名(参数列表);

malloc 和 free 函数

  • 动态内存分配,无法知道内存具体位置时,想要绑定真正的内存空间,则要用到动态分配内存,原型为 extern void* malloc(unsigned int size),空指针可以转换为任何类型的指针,size 仅仅是申请字节的大小,并不管申请的内存块中存储的数据类型,故申请内存的长度需通过“长度 x sizeof(类型)”的方式给出,使用完之后要用 free 释放内存;
  • 一个类型的指针包含三个信息:地址、步长、内容如何解析;
  • 在栈区开辟一段内存,系统会自己回收,在堆区开辟一段内存,需要手动用 free 释放;

calloc 和 realloc 函数

  • calloc 原型:void* calloc(unsigned int num,unsigned int size),num:对象个数,size:对象占据的内存字节数,功能是为已经分配的内存重新分配空间并复制内容,会自动将内存初始化为 0;
  • realloc 原型:voidrealloc(void ptr,unsigned int size),ptr:已分配的内存地址,size:重新分配的字节数

内存分区

  • C/C++中,内存分为:堆、栈、自由存储区、全局/静态存储区、常量存储区;
  • 堆:由 new 分配的内存块,一般对应一个 delete,若没用释放,则程序结束后操作系统自动回收;
  • 栈:编译器需要的时候分配,不需要时自动清楚的变量的存储区,通常是局部变量、函数参数等;
  • 自由存储区:由 malloc 等分配的内存块,必须用 free 释放;
  • 全局存储区:全局变量和静态变量的存储区域,未初始化的两者在相邻存的另一块区域,程序结束后自动释放;
  • 常量存储区:存放常量,不可修改;

sizeof 和 strlen

  • 实例
#include <iostream>
#include <string.h>

int main()
{
char str[10] = "hello";
cout << sizeof(str) <<endl << sizeof("hello")<< endl << str(str)<< endl;

system("pause");
return 0;
}
  • 结果:
  • 结论:对一个数组字符串,sizeof 不管是否初始化,只输出其预留内存大小,而 strlen()输出初始化后的字符串所占内存大小,不含'\0';

gets 和 scanf

  • gets 遇到换行符表示结束,而 scanf 遇到空格、制表符、换行则表示结束;

Unicode 字符问题

  • char 字符串可显示汉字,但字符不可以,字符连在一起用%c%c 可以输出一个汉字;

结构体

  • 结构体引用方式:结构体数组名[下标].成员名;
  • 结构体指针变量引用成员形式:(*结构体指针名).成员名、结构体指针名->成员名、结构体变量名.成员名;

结构体字节对齐机制

  • 结构体变量大小是能够被其最宽基本类型成员的大小所整除;
  • 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,若有需要编译器会在成员之间加上填充字节;
  • 结构体总大小为结构体最宽基本类型成员大小的整数倍,若有需要编译器会在最末一个成员之后加上填充字节;

共同体 union

  • 使几个不同类型的变量共占一段内存(相互覆盖),长度=最长成员所占字节数,不能同时对所有成员初始化;

深拷贝与浅拷贝

  • 深拷贝:根据指针指向的值,重新申请内存,再以此将指针指向内容复制过来,有相互独立的内存空间,一般复制构造函数和 strcpy 等函数都是深拷贝;
  • 浅拷贝:把对象(结构)里的值完全复制给另一个对象(结构),对于地址也是照抄,类的默认复制构造函数是将类中非静态成员变量逐个复制,是浅拷贝;

文件分类

按逻辑

  • 记录文件:具有一定结构的记录组成(定长和不定长);
  • 流式文件:由一个个字符(字节)数据顺序组成;

按存储介质

  • 普通文件:存储介质文件(磁盘、磁带等);
  • 设备文件:非存储介质(键盘、显示器、打印机等);

按数据组织形式

  • 文本文件:ASXII 文件,每个字节存放一个字符的 ASCII 码;
  • 二进制文件:数据按其在内存中的存储形式原样存放;

文件处理方法

  • 缓冲文件系统:高级文件系统,系统自动为正在使用的文件开辟内存缓冲区和非缓冲文件系统;
  • 低级文件系统:由用户在程序中为每个文件设定缓冲区;

fscanf 和 fprintf 函数

  • 两者遇到空格或换行时结束;

文件型结构体

struct _iobuf
{
char *_ptr;//当前缓冲区内容指针
int _cnt;//缓冲区还有多少个字符
char *_base;//缓冲区的起始地址
int _flag;//文件流的状态,是否错误或者结束
int _file;//文件描述符
int _charbuf;//双字节缓冲,缓冲 2 个字节
int _bufsiz;//缓冲区大小
char *_tmpfname;//临时文件名
};

fopen 打开模式

  • 只读模式"r"打开文件,该文件必须存在,否则打开失败,r+,rb,rb+,rt,rt+模式打开文件,文件不存在也会失败;
  • 只写模式"w"打开,文件存在则长度清 0,不存在则建立文件,w+,wb,wb+,wt,wt+模式打开文件,文件不存在则建立文件;
  • a 以附加的方式打开只写文件,若文件不存在,则建立文件,存在则在文件尾部添加数据,a+以附加的方式打开可读写文件,不存在则建立文件,存在则写入数据到文件尾,at 二进制数据的追加,不存在则创建,只能写、at+读写打开一个文本文件,允许读或在文本末追加数据,ab 二进制数据的追加,不存在则创建,只能写;

阻塞模式和非阻塞模式

  • 非阻塞模式,会引起宕机,会一直执行;
system("start notepad");
  • 阻塞模式,不会引起宕机,执行一步后才能执行下一步;
system("notepad");

⏳ 联系

想解锁更多知识?不妨关注我的微信公众号:村雨遥(id:JavaPark)

扫一扫,探索另一个全新的世界。

上次编辑于:
贡献者: 村雨遥