笔记 |C语言知识点快速过

  1. C语言由函数组成,有且只有一个主函数,且程序运行先从main函数开始,main函数由系统自动调用不需要人为调用;return 0 表示程序正常结束
  2. 头文件包含函数的声明,使用某个函数之前需要包含相应的头文件,<>包含系统的头文件,””包含自定义的头文件
  3. 函数的调用必须放在{}内部
  4. system(“”) 在一个执行文件内部执行一个外部程序,会用在Qt,MFC做图形界面调用函数
  5. C语言编译过程:(编译:翻译成机器语言)分成4部:预处理编译汇编链接
  1. 预处理:不做语法检查,头文件展开,宏定义展开;注释代码处理
  2. 编译:翻译成汇编,进行语法检查
  3. 汇编:生成目标文件(二进制文件)但还不能运行
  4. 链接:链接动态库,生成可执行文件
  1. 动态库的作用:写的程序通常都需要调用函数,函数调用类似于点菜,但菜的实现需要厨房去做出来,动态库就类似于厨房,没有动态库即使调用了函数也没有办法实现
  2. 数据类型的作用:告诉编译器这么一个类型的变量需要分配多发的内存空间;分为基本类型,构造类型(struct, union……),和指针类型(char*, int*, int**……)
  3. 进制:计算机用补码存储数据
  4. 转义字符:字符原则上包含在’’中,内部只有一个字符,但转义字符除外,转义字符–由反斜杠组成的多个字符
  5. 两个数相除,要想得到小数,分子分母必须有一个数是小数,否则结果只会取整
  6. 类型转换:1)隐式转换:在赋值的地方编译器自动给内容转换,但是注意在其他地方还是原来定义的类型;2)强制类型转换:(类型)需要转换的变量名
    整形变量不要用lf打印,浮点型变量不要用d打印,除非强制类型转换;强制类型转换原则:数据类型小的往大的转换
  7. IDE调试代码 1设断点 2调试运行
  8. vs备注快捷键 ctrl+k,rl+c 撤销快捷键 ctrl +kctrl+u
  9. 程序错误:1)编译错误即语法出错;2)运行时错误(运行时异常)
  10. 数组:有多少个[]就有多少维;内存中内有多维,都只有一维。多维数组是特殊的一维数组;C没有字符串类型,用字符数组模拟 char a[10];字符串一定是字符数组,但是字符数组不一定是字符串,只有当字符数组以字符’\0’(字符’\n’等价于数字0)结尾的时候,这个字符数组才是字符串
  11. 随机数:
  12. scanf()函数: 只取第一个空格前的字符,它不安全因为它不做越界检查,在vs中会被警告编译不通过,除非在代码第一行加#……
  13. fgets( ): char *fgets (char s, int size, FILEstream) 会把换行符也读进去;printf()不加换行符,puts()会在屏幕上显示换行符但是字符串本身没有改变
  14. strlen():测字符串长度,int len = strlen(数组名),该函数需要使用返回值,返回值就是字符串的长度,从首元素开始到结束符为止,结束符不算,而sizeof()是加上结束符的,因为sizeof()是测数据类型的长度,不会因为结束符提前结束;
  15. strcpy()字符串的拷贝, strcpy(dst,str),把str字符串的内容拷贝给dst所代表的数组,拷贝过程遇到结束符’\0’就会结束;对比strncpy()后者可以跳过前个数
  16. strcmp(s1,s2) 比较每一个字符的ASCII码,只要有一个字符大了就大了,返回值是大于0或小于0或等于0; 比较strncmp(s1,s2,n),指定比较前n个字符
  17. strcat(dst,str): 把str的内容加到dst后面;strcat(dst,str,n):指定长度追加
  18. sprintf():格式化一个字符串,把这个字符串输出(保存)到指定数组中
  19. sscanf():从指定数组中以指定格式提取内容;提取整形变量是最方便的;字符串只识别空格作为分割
  20. strchr()查询char类型,有没有指定的字符,如果找到就找到该字符所在位置的地址,如果查询失败就返回NULL
  21. strstr()查询string类型,有没有指定的字符串,如果找到就返回匹配字符串的位置,失败则NULL
  22. strtok()字符串切割:第一次切割“strtok(str,”切割字符”)”,返回值是切割后的字符串,如果没有切割成功就会返回NULL,在匹配切割字符串的地方会换成结束符,因此使用后会破坏原来的字符串结构;第二次切割“strtok(NULL,”切割字符”)”第一个参数是NULL,一半用循环写
  23. atoi:把一个字符串,如果字符串内容有整数,就可以将该整数转换成数字(把字符串转换成整形),同样有atol,atof,其实可以用sscanf()进行提取;同理,可以用sprintf()将数字转换成字符串,e.g. char buf[100]; sprint(buf,”%d”,1234)
  24. 一个字符串小总结:fgets()与gets()相比更安全,因为会有一个输入长度的参数并且可以输入\n;puts()会自动在屏幕上加\n,但是字符串本身没有变化;strlen()测字符串长度,遇到\n就停止,注意与sizeof()的不同;
  25. 函数:库函数(即系统函数)+用户定义函数
  1. 无参无返回值:没有返回值就用void关键字修饰,没有参数就用void或者不写
  2. 有参无返回值:定义函数的参数叫做形参,形参的格式必须是—类型+变量,不能赋值,函数没有调用形参不会分配空间,函数调用完毕,形参变量自动释放,函数调用时传的参数叫实参,匹配的实参可以时变量,常量或表达式,如果形参有多个,拿“,”分开
  3. 无参有返回值:函数内部通过return返回,(return作用终止当前的函数),函数返回值只能返回一个,如果return的类型和函数返回类型不一致,以函数返回类型为准
  1. 函数的声明和定义:可以只声明但是不定义函数,但是没有意义;只能定义一次但是i可以声明很多次没有关系,声明的形参和定义的形参名可以不一样,声明时也可以不写形参名,声明需要都放在被调用前
  2. 分文件编程:
  1. 按功能分 xxxx.h(.c中函数的声明) xxx.c(函数的定义)
  2. 有一个主函数测试自定义函数 main.c
  3. 不要在头文件做定义,只能用一次,第二次用就会报错:重复定义
  4. 防止同一个文件包含重复头文件:方法1):在头文件开始写:pragma once,就可以使包含多次但只有一次生效 方法2)开头写#ifndef _MYSTRLEN_H(下划线头文件的名字的大写) 和#define _MYSTRLEN_H(同样时下划线加名字的大写)结尾写#endif
  1. 内存是以1个字节为单位分配内存,每个字节的内存都有标号,即地址,地址也需要存储,32位编译器用32位(4字节)存此地址。64位编译器用64位(8字节)存此地址;内存分配编号即编码,给很具地址找到对应的内存,即寻址;概括之:内存中的每一个字节都有一个编号,该编号就是地址,如果在程序中定义了一个变量,在对程序进行编译或运行时,系统就会给这个变量分配内存单元,并确定分配的内存单元的地址,指针的实质就是内存地址,指针就是地址,地址就是指针,指针是内存单元的编号,指针变量是保存指针(地址)的变量,通常我们说指针变量会简称位指针,其实它们两者的含义不一样
  2. 指针也是一种数据类型 e.g. int* ; 指针指向谁就把谁的地址赋值给该指针int p = &a,P保存了a的地址,直接操作指针变量没有意义,需要操作p来操作指针指向的内存
  3. 野指针:保存了一个没有意义(非法)的地址的指针; 关于段错误:只有定义后的变量的地址才是合法的地址,操作野指针变量本身没有问题,操作野指针指向的变量才出错
  4. 空指针:给指针变量赋值为NULL,NULL就是数字0;预防野指针的影响
  5. 指针大小:32位编译器用32位(4字节)大小保存地址,64位编译器用64位(8字节)大小保存
  6. 多级指针:在需要保存变量地址的类型基础上加一个*
  7. []不是数组专属: *P = *(P+0)=P[0], 操作的是指针所指向的内存;
  8. 万能指针:不可以定义void类型的变量,因为不能确定类型,编译器不知道呀哦给该变量分配多少内存;但可以定义void 的变量,因为指针的内存就是根据编译器(见37),因此void指针也叫做万能指针,即void*可以指向任何类型的变量,但使用该指针所指向的内存时,最好转换为它本身的指针类型,因为不转换就没法确定指针步长
  9. const修饰的指针变量:const修饰*代表指针所指向的变量的值为不可修改,const修饰指针变量代表指针变量的值不可修改就是该指针(地址)不可修改
  10. 指针数组,它是指针的数组,每个元素都是指针;数组指针:他是指针,指向数组的指针;
  11. 如果想通过函数改变实参必须地址传递
  12. 形参中的数组:注意形参中的数组不是数组,它是普通指针变量:形参数组int a[10000], int a[], int *a对于编译器来说没有任何区别,对编译器都是 int *a,一个普通的指针变量,64为编译器读出来sizeof(a)就是等于8;要用到数组元素个数的时候需要将元素个数传过去;
  13. (易错!)每个字符串都代表一个地址,这个地址就是字符串首元素地址;字符串常量放在data区,也叫做文字常量区,又,文字常量区的字符串只能读不能改,文字常量区的生命周期和全局变量一样,程序结束才释放
  14. main形参使用说明:int main(int argc, char * argv[]) : argv[]是数组,数组每个元素都是char*, 每个元素都是字符地址 ; argc:argv[] 元素的个数 ; main() 函数参数需要用户传递
  15. 普通/static局部变量;普通/static局部变量;普通/static函数 的区别:
  1. 在{}内部定义的变量就是局部变量,只有执行到定义变量的这个语句,系统才会给这个变量分配空间,离开{},这个非static局部变量会自动释放;{}的普通局部变量加不加关键字auto都是一样的,普通局部变量也叫做自动变量;如果不初始化默认值为随机数
  2. Static(静态)局部变量: 静态局部变量会在编译阶段就分配空间即函数调用之前就已经存在了;当然作为局部变量也是在{}内定义的,但是当离开{},static局部变量不会释放,只有程序结束才自动释放,但作用域还是在{}内;如果静态局部变量不初始化,默认为0;静态局部变量的初始化语句只会执行一次,但是可以赋值多次;注意:只能用常量给初始化
    =====> 普通局部变量只有执行到定义变量的语句才分配空间,static局部变量在编译阶段即函数还没有执行的时候就分配空间了;普通局部变量离开作用域{}就会自动释放,static局部变量只有在整个程序结束的时候才会释放;普通局部变量不初始化值为随机数,static不初始化默认值为0,且只能用常量初始化并且只有第一次执行
  3. 普通全局变量(外部链接):在函数外面定义的为全局变量,只要定义了全局变量就能在任何地方使用此变量;如果在使用此变量时在前面找不到这个全局变量的定义就需要声明才能使 “extern int a”; 声明时不要赋值;全局变量不初始化默认赋值为0;全局变量只能定义一次但能声明多次,不同文件全局变量也只能声明一次;在变异结算就已经分配空间,在整个程序结束才自动释放;===》全局变量的缺陷:如果定义一个全局变量,没有赋值(初始化),就无法确定时定义还是初始化=》所以定义一个全局变量就建议初始化,如果声明一个全局变量就加关键字extern
  4. static全局变量(内部链接):与普通全局变量的文件作用域不一样,普通全局变量所有的文件在声明之后都能使用,但static全局变量只能在本文件使用,别的文件不能使用;不同的文件只能出现一个普通全局变量的定义但static全局变量只要保证一个文件没有相同定义就行,不同文件间的static全局变量是没有关系的2个变量
  5. 普通函数和static函数:所有文件只能由一次普通函数的定义而static函数只要在一个文件中不重复就行;普通函数可以被所有文件调用,只要提前声明,static函数只能在此函数定义的文件中使用
  1. 内存分区介绍(面试问):在程序没有执行前,有几个内存分区已经确定,但是虽然分区确定,还没有加载内存,程序只有运行时才能加载内存,有:
  1. text(代码区):只读,函数入口地址,用户不关心;
  2. data区:初始化的数据:全局变量,静态变量,文字常量区(只读);
  3. bss区:没有初始化的程序,全局变量,静态变量
  4. stack(栈区):普通局部变量。自动管理内存,先进后出的特点
  5. heap(堆区):手动申请空间,手动释放,整个程序结束,系统也会自动回收;如果没有手动释放程序也没有结束,这个堆区就会一直在
    当程序运行,会加载内存,首先根据前面确定的内存分区(text,data,bss)先加载,然后额外加载另外两个区
  1. 几个内存操作函数: 需要#include<string.h>
  1. memset:void *memset(void *s, int c, size_t n) 将s的内存区域的前n个字节用参数c填入,返回s的首地址,(中间参数虽然是整形但以字符处理,基本定为0)
  2. memcpy:字符串的操作数遇到’\0’就会停止剩下的不会再拷贝但是内存操作函数操作的是内存,不会因为内容产生影响;e.g. memcpy(b,a,sizeof(a));把a的内容拷贝给b,注意1第三个参数是指拷贝内存的总大小;注意2使用这个函数最好别出现内存重叠;
  3. memmove()如果出现内存重叠用这个函数memmove(&a[2],a,5*sizeof(int))
  4. memcmp()
  1. 指针指向堆区,平时指针指向一个普通变量的都是指向栈区的,指向堆区:#include, int*(malloc(sizeof(int))) 参数就是指定堆区需要分配多大的空间,返回值,成功的话就是堆区首元素地址,失败返回NULL;注意:1动态分配的空间,入股哦程序没有结束不会自动释放;2 一般使用完,不要人为释放free; 3 free§不是释放p变量,释放的是p所指向的内存 4 同一块堆区内存只能释放一次 5 所谓的释放不是指内存小时,是指这块内存用户不能再使用了,系统回收了,如果用户再使用就是操作非法用户
  2. 内存泄漏:动态分配了空间,不释放; 内存污染:非法使用内存
  3. #include<conio.h>接受字符,敲完之后不用按回车
  4. 结构体:在C中,”struct name” 这一个整体才是一个变量类型,结构体成员不能直接使用,需要借助结构体变量来引用:如果是普通变量用. ; 如果是指针变量用->
  5. 相同类型的2个结构体变量可以相互赋值
  6. 共用体(联合体):union关键字-结构体的大小可以简单人为是成员大小的累加,但共用体的大小为最大成员的大小,共用体公有一块内存,所有成员的地址都一样;给某个成员赋值会影响到另外的成员
  7. 枚举:enum关键字,里面的成员是一个标识符,枚举常量,第一个成员如果没有赋值,默认为0,下一个比上一个多1;可以使用枚举成员给枚举变量赋值
  8. typedef: 不能创建新类型,就是给一个已存在的类型起一个别名
  9. 文件:FILE所有平台的名字都一样,FILE是一个结构体类型,在不同的平台成员的名字不一样但是成员功能都是一样的; 指针文件:FILE *fp ; 1)fp指针只要调用了fopen(),就会在堆区分配空间,并把地址返回给fp ,2)fp指针不是指向文件,fp指针和文件关联,fp内部成员保存了文件的状态, 3)操作fp指针,不能直接操作必须通过文件库函数来操作fp指针, 4)通过库函数操作fp指针,对文件的任何操作,fp里面的成员会相应发生变化 ======>fp是一个指针,指向一个内存空间,改内存空间和硬盘相关联
  10. 打开文件fopen(); 读写文件1)按字符读写fgetc(),fputc() 2)按字符行读写fgets(), fputs() 3)文件结尾判断feof(); 关闭文件fclose()
  11. Windows文件绝对路径写法:/ 或者\ ; 相对路径:a)编译同时运行程序相对路径相对于****.vcxproj(项目文件)所在的路径 b) vs中:如果直接运行程序,相对路径相对于可执行程序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值