C语言的乱七八糟
Note For C
Linux下C编程基础(gcc/gdb/make使用)
一.vi学习
二.初探emacs
三.gcc编译器
3.1 gcc所支持后缀名解释
后缀名 |
解释 |
后缀名 |
解释 |
.c |
C原始程序 |
.s/.S |
汇编语言原始程序 |
.C/.cc /.cxx |
C++原始程序 |
.h |
预处理文件(头文件) |
.m |
Objective-C原始程序 |
.o |
目标文件 |
.i |
已经预处理过的C原始程序 |
.a/.so |
编译后库文件 |
.ii |
已经预处理过的C++原始程序 |
|
3.2 gcc编译流程
A.预处理(pre-processing)
对头文件及宏定义进行处理.
B.编译(compiling)
检查代码规范性以及是否有语法错误,待检查无误后将代码翻译为汇编代码.
C.汇编(assembling)
将上一阶段的汇编代码转变为目标代码.
D.链接(linking)
将函数库中的函数与目标文件进行链接.
3.3 gcc常用编译选项参数
参数 |
作用 |
-c |
只编译不链接,生成目标文件”.o” |
-S |
只编译不汇编,生成汇编代码 |
-E |
只进行预编译,不做其他处理 |
-g |
在可执行程序中包含标准调试信息 |
-o file |
指定file为输出文件 |
-v |
打印出编译器内部编译各过程的命令行信息和编译器版本 |
-I dir |
在头文件的搜索路径中添加dir目录 |
在C程序中”<>”表示在标准路径中搜索头文件,” “” ”表示在本目录中搜索头文件!
3.4 gcc编译库参数
四.gdb调试器
4.1使用流程
A.使用gcc将源代码编译为可执行文件(gdb调试可执行文件);
B.gdb调试(交互式)
l(list)--->查看载入文件;
help--->查看帮助信息;
b num--->在行号为num处设置断点(运行到num行之前暂停);
info b--->查看断点信息;
bt--->查看调用函数(堆栈)的情况;
r--->运行代码;
p variable_name--->查看变量值;
n/s--->单步运行(有函数调用时候s会进入函数,而n不会);
c--->恢复程序运行(查看所需变量及堆栈情况后).
4.2 gdb基本命令
4.2.1工作环境相关命令
命令用法 |
作用 |
set args 运行时参数 |
指定运行时参数 |
show args |
查看设置好的运行参数 |
show paths |
查看程序运行路径 |
set environment var[=value] |
设置环境变量 |
show environment[var] |
查看环境变量 |
cd dir |
进入dir目录 |
pwd |
显示当前工作目录 |
shell command |
运行shell的command命令 |
第一部分C语言基础
第一章 C语言概述
1.1 C语言简史
1.2 C是中级语言
1.2.1作为中级语言,C允许对位/字节/地址进行操作;
1.2.2易于移植;
1.2.3 C拥有5种固定的基本数据类型,但几乎允许所有类型的数据转换;
1.2.4 由于C运行时几乎不进行错误检查,故而程序员应对代码进行检查;
1.3 C是结构化语言
1.3.1代码和数据的封装;
1.3.2 局部变量与全局变量/函数的定义;
1.4 C是面向程序员的语言
1.5 术语
源代码(source code) |
用户可阅读的程序文本(程序),为C编译程序的输入 |
目标码(object code) |
由源代码经编译而来的计算机可直接读入并执行的机器码,为链接程序的输入 |
链接程序(linker) |
可将分别编译的函数链接为完整程序的程序,能够将C的标准库函数与代码结合,其输出为可执行代码 |
函数库(library) |
存放可被用户程序引用的标准函数的文件,包含了I/O操作及其他子程序 |
编译时(compile time) |
编译时出现的事件 |
运行时(run time) |
运行时出现的事件 |
1.6 编译和解释
1.6.1 编译(compiled):
1.6.2 解释(interpreted):
1.7 C程序的格式
1.7.1 C语言关键字
1.8 库和链接
1.8.1 函数库:包含许多既定函数,编写代码时可以直接调用其中的函数;
1.8.2 连接程序与链接:当程序员编写好代码之后,编译程序编译源码,编译过程中遇到库中的函数时,链接程序(linker)将我们所编写的源码与函数库中的目标代码相结合,该过程称为链接(link);
1.8.3 连接程序:C编译程序自带/操作系统自带
1.8.4 函数库中的函数为可重定位(relocatable)函数,其地址段内偏移量确定;
1.9分别编译
程序过长会增加编译时间,故而可将一个程序分解为若干块(装入若干文件),进行单独编译.可节省大量时间,而且某个部分改变换不必重新编译全部文件.
1.10 编译C程序
1.11 C的内存映像
编译完成的C程序取得并使用4块在逻辑上不同且用于不同目的的内存区域,其实际物理布局随CPU类型和编译程序的实现而改变,以下为其概念图.
栈(stack) |
|
保存函数调用返回地址/函数变元/局部变量/CPU当前状态 |
堆(heap) |
|
自有内存区域 |
全局变量 |
|
|
程序代码 |
|
|
1.12 C和C++
1.12.1 C是C++的子集;
1.12.2 C程序拓展名为.c , C++程序拓展名为.cpp;
第二章 表达式
2.1基本数据类型
字符型:char,1字节
整型:int,随环境变换
浮点型:float,
双精度浮点型:double
无值型:void,既可明确表示无返回值函数,又可生成各种元素的指针
_Boll:
_Complex:
_Imaginary:
2.2 修饰基本类型
有符号:signed
无符号:unsigned
长型:long
短型:short
signed与unsigned的区别在于如何区分整数的最高位,有符号整数则最高位为其符号位(0---正,1---负).
2.3标识符命名
2.3.1 标识符:变量/函数/符号/用户定义的对象名称(长度不限);
2.3.2 标识符第一为必为下划线或字母,之后可取字母/数字/下划线;
2.3.3 内部标识符/外部标识符,区分大小写,不能与关键字相同.
2.4 变量(variable)
2.4.1 变量:内存中已命名的位置,放置可修改的值,使用之前定义,格式: variable_type variable_name (variable_name可由一个或多个由逗号分隔的标识符构成);
2.4.2
函数内 |
局部变量(local variable) |
只有定义它的代码块可访问 |
函数外 |
全局变量(global variable) |
无论何处均可访问 |
函数参数的定义中 |
形式参数(form parameter) |
退出函数时被销毁 |
2.4.3 C语言的四个域
文件域 |
|
块域 |
|
函数原型域 |
|
函数域 |
|
2.5 类型修饰符
2.5.1 类型修饰符:C语言定义的控制如何访问或修改变量的类型的修饰符,置于数据类型之前;
2.5.2 const:不可修改,但可赋予初始值,通常用于只读区域;
2.5.3 volatile:把事实告知编译程序(变量的值能以未在程序中明确表达的方法改变);
2.5.4 restrict:
2.6存储类型说明符
2.6.1存储类型说明符:告之编译程序如何保存变量,置于变量申明之前,格式 storage_specifier variable_type variable_name;
2.6.2 extern:
外部链接 |
函数/全局变量 |
对构成程序的所有文件可用 |
内部链接 |
申明为static的文件域对象 |
仅在申明他们的文件中已知 |
无链接 |
局部变量 |
仅在自己所属的块中已知 |
声明:表述对象的名称和类型.
定义:不仅表述对象的名称和类型,还为对象分配存储空间,使用extern可以只申明对象而不定义;
extern用于说明在程序的其他地方用外部链接声明的对象(就是告知编译程序变量已经在别的地方声明);
2.6.3 static:保持变量永久不变,局部静态变量仅在函数或文件中才能看到;
2.6.4 register:
register变量存储在寄存器中,故而操作速度快,但因寄存器不能编址,故而不可用&获取其变量地址;
只能用于局部变量与形式参数,通常用于多次引用同一变量的地方.
2.7变量初始化
2.7.1 全局变量/静态全局变量在程序运行时初始化,
2.7.2 局部变量/静态局部变量进入被定义的代码块时初始化;
2.7.3 局部变量不经初始化,初值不确定;未初始化的全局变量/静态局部变量为0;
2.8 常量
2.8.1 字符串--->”” 字符--->’’
2.8.2 转义字符
2.9 操作符
2.9.1 赋值操作符---> =
类型转换;
char x;int i;x=i;
多重赋值;
x=y=z=9;
复合赋值;
x +=10;
2.9.2 算术操作符
操作符 |
作用 |
注意 |
- |
减法 |
|
+ |
加法 |
|
* |
乘法 |
|
/ |
整除 |
|
% |
模除(取余) |
不适用于浮点数 |
-- |
减量 |
增减一个单位的量;操作符在前则先加减再使用,操作符在后则先使用后加减. |
++ |
加量 |
2.9.3 关系逻辑操作符
true---> 非零值,false---> 0
关系操作符 |
逻辑操作符 |
||
> |
大于 |
&& |
与 |
>= |
大于等于 |
|| |
或 |
< |
小于 |
! |
非 |
<= |
小于等于 |
|
|
== |
等于 |
|
|
!= |
不等于 |
|
|
2.9.4位操作符
应用于char与int,不能应用于float/double/long/void等复杂类型;
操作符 |
作用 |
用途 |
& |
与 |
清除某些位 |
| |
或 |
置位 |
^ |
异或(只有一个真才为真) |
用于屏蔽某些位 |
~ |
求1的补 |
|
>> |
右移 |
|
<< |
左移 |
|
2.9.5问号操作符(三元运算符)
exp1?exp2:exp3
2.9.6指针操作符&与*
指针(point)是变量的内存地址;指针变量(pointer variable)是存放指向相应类型的指针;
指针三个主要功能:A.帮助快速引用数组元素 B.允许函数修改调用变元的内容 C.支持链表及其他数据结构;
取地址符(&):一元操作符,返回操作数的内存地址,例如 m=&count 将count变量的内存地址赋予m;
取值符(*):一元操作符,返回操作数所示地址处的值,例如 n=*m 将m地址处的值(即count的值)赋予n;
指针变量必须在定义时使用*符号声明,例如 char * ch,此处ch为指向字符变量的指针,而非字符变量;
2.9.7 编译时操作符sizeof()
sizeof():一元操作符,其操作数需置于()中或舍去(),返回其操作数的字节数.
2.9.8 逗号(,)操作符
逗号(,):将若干表达式连接在一块,使其按一定顺序进行,例如 x=(y=3,y+1) 即将3赋予y,然后y+1,最后x=4;
2.9.9 圆点(.)与箭头(->)操作符
2.9.10 []和()操作符
2.9.11 操作符优先级小结
一元操作符(*,&,-)和问号操作符(?)为右结合,其余均为左结合;
2.10 表达式
2.10.1 表达式的子表达式以未定顺序求值,C语言允许编译程序自由重排表达式顺序,以求最优代码,例如 F=f1()+f2() 并不一定先调用f1()再调用f2();
2.10.2 类型提升:同一表达式中混有不同类型变量或常量时,编译程序会将其转换为该表达式中尺寸最大的操作数类型;整数提升:char / short int --->int;
2.10.3 强制类型转换:一元操作符,格式 (variable_type) expression;
2.10.4 空格和括号
第三章 语句
3.1 C的真值和假值
真值---> 任意非零值,假值---> 0;
3.2 选择语句
3.2.1 if语句
if(expression)
statement1;
else
statement2;
如果expression为真,则statement1,否则statement2.
3.2.1 嵌套if语句
多个if语句相嵌套
3.2.3 if-else-if梯次
if(expression1) statement1;
else
if(expression2) statement2;
else
if(expression3) statement3;
...
3.2.4 代替if的问号(?)
三元运算符
expression1?expression2:expression3
3.2.5 条件表达式
3.2.6 switch
将一个表达式的值和一个整数或者字符常量表中的元素逐一比较,匹配则执行;
格式:
switch(expression){
case constant1:
statement1
break;
case constant2:
statement2
break;
...
default:
statement
}
switch只能测试是否相等,每一个case(标号)必须各异,且switch中即使使用字符常量也是被自动转换为整数.
3.2.7 嵌套switch语句
3.3 重复(iteration)语句
3.3.1 for循环
格式:
for(initialization;condition;increment)
statement;
initialization:初始化,一般为赋值语句,为循环的控制变量置初值;
condition:关系表达式,确定何时退出循环;
increment:增值,定义每一次循环如何修改控制变量;
3.3.2 for循环的变形
3.3.3 无限循环
3.3.4 在for循环中声明变量
3.3.5 while循环
格式:
while(condition)
statement;
3.3.6 do-while循环
格式:
do{
statement;
}while(condition);
3.4 转跳语句
3.4.1 return语句
return用于函数返回,使函数返回到被调用的地方;
return可有也可没有相关值,有相关值的return仅能用于非void返回类型的函数中;
函数执行到return即结束执行;
3.4.2 goto语句
goto必须和label在同一函数中,不能跨函数转跳;
格式:
label:
statement;
goto label;
其中label可以为任何有效标识符.
3.4.3 break语句
用于在switch中终止一个case或者强制终止循环;
break只作用于与之最相近的循环;
3.4.4 exit()函数
需要头文件<stdlib.h>,用于结束整个程序(一般返回操作系统);
零值表示正常结束,非零值表示某种错误;
3.4.5 continue语句
用于强制跳过当前循环进入下一轮循环;
3.5 表达式语句
3.6 块语句
以{开始,以}结束;
第四章 数组和字符串
数组由连续内存构成,最低地址对应首元素,最高地址对应末元素.
4.1 一位数组
格式: variable_type var_name[size];
数组使用0作为其实下标,末尾下标为size-1;
使用下标访问/修改元素;
数组总字节数=sizeof(variable_type)×数组长度
4.2 指向数组的指针
例如:
int *p;
int sample[10];
p=sample;
/*p指向了数组sample的首元素地址*/
4.3 向函数传递一维数组
4.4 串
4.4.1 字符串由实际字符加末尾空字符(null/0)构成,字符串数组的长度为实际字符数量加一;
4.4.2 常用字符串函数
函数名 |
作用 |
strcpy(s1,s2) |
将s2拷贝到s1 |
strcat(s1,s2) |
将s2连接到s1末尾 |
strlen(s1) |
返回s1的长度 |
strcmp(s1,s2) |
s1=s2 返回0 |
s1>s2 返回正值 |
|
s1<s2 返回负值 |
|
strchr(s1,ch) |
返回指针,指向ch在s1中第一次出现的位置 |
strstr(s1,s2) |
返回指针,指向s2在s1中第一次出现的位置 |
4.5 二维数组
格式:variable_type var_name[size1][size2];
二维数组保存在一个行列矩阵中,第一个下标表示行,第二个下标表示列;
数组总字节数:
第一维大小×第二维大小×sizeof(variable_type);
4.5.1字符串数组
存取数组中字符串非常简单,只需说明第一维下标即可;
4.6 多维数组
格式:
Variable_type var_name[size1][size2]...[sizen]
由于受内存限制,且计算各维下标浪费时间,所以大于三维的数组并不常用;
4.7 指针的下标操作
4.7.1 不带下标的数组名就是指向数组首元素的指针指针运算一般快于数组下标运算;
4.7.2 下标引用与指针引用
一维数组 a[size]
a[i]==*(a+i)
二维数组 a[size1][size2]
a[j][k]==*((基类型 *)a+(j*行长度)+k)
4.8 数组初始化
格式:
var_type var_name[size1][size2]...[sizen]={value_list};
value_list是用逗号分隔的常量表;
例如:
int i[10]={1,2,3,4,5,6,7,8,9,10};
int a[2][2]={{1,2},{2,2}};
char str[9]=”i like c”;(char str[9]={‘i’,’ ‘,’l’,’i’,’k’,’e’,’ ‘,’c’,’\0’};)
###无尺寸数组初始化
char s1[12]=”read error\n”;
char s1[]=”read error\n”;
4.9 可变长数组
4.10 一担跳游戏(不完善,仍要改进)
第五章 指针
5.1 什么是指针
指针(pointer)是存放内存地址的变量,其中存放了另一个变量的内存地址.
5.2 指针变量
基类型 星号 变量名
var_type *var_name;
基类型确保兼容;
5.3 指针操作符
&:一元操作符,返回操作数地址;
*:一元操作符,求操作数所指变量的值;
5.4 指针表达式
与一般表达式一致;
5.5 指针算术操作
增减量操作符(++/--):指针增/减量后指向下/上一个与之同基类型的元素;
和整数进行加减法操作;
指针间相减;
5.6 指针比较
比较指针之间内存地址的先后顺序.
5.7 指针和数组
5.7.1访问数组的两种方法:
- 指针算术
- 数组下标
5.7.2 指针数组
例如:
int *x[10];
/*将整型变量var的地址赋予指针数组的第三个元素*/
x[2]=&var;
/*找到var的值*/
*x[2];
5.8 多级间址(multiple indirection)
一个指针指向另一个指向目标值的指针(指向指针的指针);
声明:var_type ** var_name;
5.9 指针初始化
非静态的局部指针已声明但未赋值前,其值不确定,全局指针和静态局部指针自动初始化为零;
一般情况下对于当前没有指向合法的内存地址的指针,为其赋值null(0);
5.10 函数指针
5.11 动态分配函数
5.11.1C动态分配函数从堆(heap,系统的自由内存区,容量一般较大)取得内存;
5.11.2函数(包含于头文件<stdlib.h>)
- malloc():分配内存,用法:
pointer_name=malloc(number_bytes);失败则返回null;
- free():释放内存;用法:
free(pointer_name);
5.11.3 动态分配的数组
5.12 由restrict修饰的指针
5.13 与指针有关的问题
A.未初始化
小程序运行时,指针随机指向”安全”区的可能性很大,既不指向程序的代码和数据,也不指向操作系统;然而当程序增大时,指针指向重要区域的概率增加;
B.错误理解指针
第六章 函数
6.1 函数的一般形式
return_type function_name(parameters_list){
function_body
}
return_type:返回数据类型(除数组外);
parameters_list:参数表,用逗号隔开;
6.2 函数的作用域规则
6.3 函数的变元
值调用:将变元值拷贝到形参,形参修改不影响变元;
引用调用:将变元地址拷贝到形参,通过地址访问变元,形参修改影响变元;
数组调用:当数组作为变元时,传入函数的只是数组的地址,函数中代码对数组进行实际操作;
6.4 main()函数中的变元argc和argv
A.argc为整型变量,存放命令行中的变元个数,包括程序自身,故argc最小值为1;
B.argv:形参,指针,指向字符串指针组成的数组,数组中的每一个元素指向一个命令行变元;
#命令行变元之间必须用空格或制表符分隔,逗号和分号不是分隔符;
6.5 返回语句
return类型/返回指针类型/void类型;
6.6 main()的返回值
6.7 递归
使用递归时,从栈上为局部变量和参量分配存储空间并从头执行函数代码,递归函数并不复制函数代码,只是重新分配相应变量,递归使用不当会造成堆栈溢出;
当每一个递归返回时,其局部变量和参数的存储空间都释放回栈中;
使用递归时,需要适当使用使用if语句以终止递归调用;
6.8 函数原型
6.9 定义可变函数的参数表
使用...(三圆点)表示可能仍有函数参数的声明,但必须包含一个实际参数;
例如:
int func(int a,int b,...);
/*表示除了a和b,可能仍有参数*/
6.10 “隐含的int”规则(C99中已取消)
6.11 参数声明的老式方法和现代方法(推荐)
A.老式方法:一个参数表位于函数名之后的括号中,实际参数位于另一个独立的闭圆括号或开大括号中;
B.现代方法:参数实际声明位于函数名后面的括号中;
例如:
float f(int a,int b,char h){ /*现代方法*/
Function_body;
}
float f(a,b,h){ /*老式方法*/
Function_body;
}
int a,b;
char h;
6.12 inline关键字
第七章 结构/联合/枚举和用户定义类型
7.1 结构
7.1.1结构:在一个名下引用的多种变量的集合,把相关的数据组合到一块,结构定义(structure definition)形成一个样板,用于生成结构变量,构成结构的变量称为成员(member)/元素(element)/域(filed);
7.1.2 结构定义格式:
struct structure_name{
member_name;
};
##此时只定义了数据的形式,什么变量也没用生成;
7.1.3 结构变量声明
A.结构定义之后
struct structure_name strcucture_var;
##此处定义了structure_name类型的结构变量structure_var,structure_name描述结构,structure_var是结构的实例(对象);
B.结构定义时
struct structure_name{
relative_name;
}structure_var_list;
- 若只定义一个结构变量则结构标记(structure_name)可省略
struct structure_name{
relative_name;
}structure_var;
7.1.4 访问结构成员
通过.(圆点)存取结构中的成员;
格式:structure_var.member_name
7.2 结构数组(array of structures)
7.3 向函数传递结构
7.3.1 传递成员
7.3.2 传递全结构:全局的变量
7.4 指针结构(->)
7.5 结构中的数组和结构(嵌套)
7.6 联合(共享内存)
格式:
union union_name{
var_type member_name;
var_type member_name;
...
}union_var;
/*变量声明可以在末尾也可以union union_name var_name*/
##编译时,编译程序自动生成联合中最大元素的内存;
7.7 位域
7.7.1 定义:C语言具有访问字节中位的的机制,称为位域(bite-field);
7.7.2 用途:
A.内存紧张时,将布尔变量存入一个字节;
B.将编码信息传输到各个位;
C.某些加密算法需要访问字节中的位;
7.7.3 形式: type_name:length;
type:指定位域类型,包括int/signed/unsigned/_BOOL
7.7.4 限制:不能取位域变量的地址/不能构成数组位域/不能跨越整数边界;
7.8 枚举
7.8.1 形式:enum name{enumeration_list}variable_list;
name和variab_list可选但至少要出现一个;
7.8.2 声明枚举变量:
enum name var_name;
7.9 C和C++之间的重要区别
声明结构/联合/枚举时C++中可以不用使用关键字!!!!
7.10 使用sizeof确保可移植性
7.11 typedef
一般形式: typedef type neuname;
将neuname替代type使用;
第八章 控制台I/O(头文件---> <stdio.h>)
8.1 读写字符
getchar():从键盘读取一个字符,等待击键,击键后将读取值返回并将击键结果回应到屏幕;
putchar():向屏幕当前光标处显示一个字符;
8.1.1 getchar()的问题:输入先被缓冲,键入enter才返回(行缓冲---> line-buffer);
8.1.2 代替getchar()的函数
getch():在击键后立即返回,不需要键入enter,不向屏幕回显字符;
getche():
8.2 读写字符
puts():从控制台读取字符串,需要回车(函数会自动忽略回车符,如何在字符串末尾加null终止符);
gets():向控制台写字符串,如何再写一个新行符;
函数 |
操作 |
注意 |
getchar() |
从键盘读取字符 |
等待回车 |
getche() |
读取字符并回显 |
不等回车 |
getch() |
读取字符不回显 |
不等回车 |
putchar() |
向屏幕写字符 |
|
gets() |
从键盘读取字符串 |
|
put() |
向屏幕写字符串 |
|
8.3 格式化控制台I/O
8.3.1 printf():
代码 |
格式 |
|
%a |
以格式0x....输出十六进制数 |
|
%A |
|
|
%c |
字符 |
|
%d |
带符号十进制整数 |
|
%i |
带符号十进制整数 |
|
%e |
科学表示(e表示指数部分) |
|
%E |
科学表示(E表示指数部分) |
|
%f |
十进制浮点数 |
|
%g |
在%e或%f中择短使用 |
|
%G |
在%E或%f中择短使用 |
|
%o |
无符号八进制数 |
|
%s |
字符串 |
|
%u |
无符号十进制整数 |
|
%x |
无符号十六进制(小写) |
|
%X |
无符号十六进制(大写) |
|
%p |
显示指针 |
|
%n |
相应变元是指向整数的指针,至此已写的字符数被printf()放入其中 |
|
%% |
显示百分号 |
最小宽域说明符:百分号和格式码之间的整数,默认补空格;
精度说明符:位于最小宽域说明符之后,由.及整数构成;
对齐输出:默认左对齐,加-后强制右对齐;
8.3.2 scanf():
A.必须向scanf传地址;
B.忽略输入:当在域的格式码之前放置*号时,使scanf()读入该域但不向任何变量赋值;
第九章 文件I/O
9.1 C与C++I/O
C是C++的子集,C++可使用C的I/O.
9.2 标准C的I/O和UNIX C的I/O
9.3 流和文件
9.3.1 C语言的I/O系统给程序员提供了与设备无关的一致界面,即C的I/O系统在程序员和设备间提供了一级抽象,这种抽象被称为”流”;实际设备被称为文件;流和文件之间具有交互作用;
9.3.2 流的性质完全类似,分为文本流(text)和二进制流(binary);
A. 文本流:字符序列,读入/写出的字符与外设之间没有一一对应关系;
B. 二进制流:字节序列,与外设字节序列一一对应;
9.3.3 文件的能力可能不同
9.4 文件系统基础
9.4.1 C文件系统由若干相互联系的函数构成,包含于头文件<stdio.h>
9.4.2 常用缓冲文件系统函数
名称 |
功能 |
fopen() |
打开一个文件 |
fclose |
关闭一个文件 |
putc() |
向文件写一个字符 |
fputc() |
向文件写一个字符 |
getc() |
从文件中读取一个字符 |
fgetc() |
从文件中读取一个字符 |
fgets() |
从文件中读取一个字符串 |
fputs() |
写字符串到文件 |
fseek() |
在文件中定位于特定字节 |
ftell() |
返回当前文件位置 |
fprintf() |
与文件关系和print和控制台关系相同 |
fscanf() |
与文件关系和print和控制台关系相同 |
feof() |
到达文件尾时返回真值 |
remove |
删除一个文件 |
rewind() |
把文件的定位指针置于文件开始出 |
fflush() |
对一个文件清仓(将文件的流全部写入外设,类似于python中fflush) |
9.4.3 文件指针:指向定义文件操作信息的指针,包括文件的名称/状态/当前读写位置;本质上,文件指针标识一个特定磁盘文件,被相连的流用来指导缓冲文件函数的操作;其为FILE型指针变量;
格式:FILE *fp;
9.4.4 打开文件
A.fopen()打开一个流,并将该流和一个文件关联,返回有关文件指针(返回空文件指针表示fopen()失败);
B.常见打开方式
方式 |
意义 |
r |
“只读”打开文本文件 |
w |
“写生成”打开文本文件--->生成覆盖 |
a |
向文本文件追加 |
rb |
“只读”打开二进制文件 |
wb |
“写生成”打开二进制文件--->生成覆盖 |
ab |
向二进制文件追加 |
r+ |
“读写”打开文本文件 |
w+ |
“写生成”打开文本文件--->生成覆盖 |
C.一般在对文件进行其他操作时要检查fopen()是否成功;
9.4.5 关闭文件
A.fclose()用于关闭fopen()打开的流,将遗留在缓冲区的数据写入文件,并关闭文件,同时释放与流关联的文件控制块(操作系统);
B.fclose()返回0表示关闭成功(一般是驱动器中无盘或盘空间不够时失败);
9.4.6 写字符
9.4.7 读字符(读取到文件尾或发生错误时返回EOF)
9.4.8 使用feof():到达文件尾时返回真值;
9.4.9 用fputs()和fgets()处理字符串
9.4.10 rewind()
9.4.11 ferror():最近一次文件操作出错时返回真值;
9.4.12 删除文件remove():成功时返回0;
9.4.13 对流清仓fflush():成功时返回0;
9.5 fread()和fwrite():
A.用于读/写长于一个字节的数据类型;
B.原型:
size_t fread(void * buffer,size_t num_bytes,size_t count,FILE *fp);
size_t write(const void * buffer,size_t num_bytes,size_t count,FILE *fp);
9.6 fseek()和随机存取I/O
int fseek (FILE *fp,long int num_bytes,int origin);
fp为fopen()返回的指针;
长整型num_bytes是从原点origin到新位置的字节数;
origin取stdio.h中定义的下列宏之一(文件开始---> SEEK_SET/当前位置---> SEEK_CUR/文件结尾---> SEEK_END),从什么地方开始寻找用什么;
查询当前文件指针位置:
long int ftell(FILE *fp);---> 失败则返回-1;
9.7 fprintf()和fscanf()
int fprintf(FILE *fp,const char * control_string,...);
int fscanf(FILE *fp,const char * control_string,...);
9.8 标准流
标准流是文件指针;
C程序运行时自动打开并自动关闭三个流:
标准输入---> stdin --->用于从控制台读
标准输出---> stdout --->用于向控制台写
标准错误---> stderr --->用于向控制台写
第十章 预处理程序和注释
10.1预处理程序独占一行并以#开头
10.2 #define:定义一个标识符和一个字符串,程序中发现该标识符则用该字符串代替,该标识符称为宏名字(macro name),该替换称为宏代换(macro substitumlition)
宏名字与字符串之间可有多个空格,结尾不加符号(;);
格式:#define macro_name macro_substitulition
10.3 #error
10.4 #include
尖括号和双引号决定了对指定文件的搜索方式;
尖括号--->搜索按编译程序作者的定义进行,一般拥有搜索某些专门放置包含文件的特殊目录;
双引号--->搜索按编译程序实现时的规定进行,一般指搜索当前目录,如若搜索未发现则再按尖括号方式搜索一遍;
10.5 条件编译指令
10.5.1 #if #else #elif #endif
10.5.2#ifdef--->如果已定义 #ifndef--->如果未定义
10.6 #undef:删除已经定义的宏名字
格式:#undef macro_name
10.7使用defined:确认是否被定义;
格式:defined macro_name
已定义--->返回真
未定义--->返回假
10.8 #line
10.9#pragma
10.10预处理操作符#和##
10.11预定义宏
10.12注释
多行注释--->/**/
单行注释--->//
第二部分
第十一章 C99
11.1C89与C99概述
11.2由restrict修饰的指针
第三部分
第十二章链接、库和头部
12.1.1链接程序作用:
- 组合(链接)各段目标码(object code)
- 清除目标文件(object file)的可重定位信息中的跳转和调试地点
12.1.2分别编译
- 先分别编译构成程序的各个文件,然后在链接,最终构成可执行文件
- 编译程序--->可重定位的目标文件 链接程序--->可执行文件
- 链接程序作用:
将链接表中的文件物理地的组合成为一个程序文件;
消除外部引用
###外部引用的产生:
一个文件引用其他文件中的代码;函数调用或使用全局变量;
12.1.3可重定位代码与绝对代码
12.1.4覆盖链接
12.1.5DLL链接
12.2.1C标准库
12.3.1头部
标准头部
头部 |
用途 |
<assert.h> |
定义宏assert() |
<ctype.h> |
处理字符 |
<erro.h> |
错误报告 |
<float.h> |
定义与现实有关的浮点值 |
<limits.h> |
定义与现实有关的各种极限 |
<locale.h> |
支持函数setlocale() |
<math.h> |
数学库使用的各种定义 |
<setjump.h> |
支持非局部转跳 |
<signal.h> |
定义信号量 |
<stdarg.h> |
支持变长度变元表 |
<stddef.h> |
定义某些常用常数 |
<stdio.h> |
支持文件I/O |
<stdlib.h> |
其他各种声明 |
<string.h> |
支持串函数 |
<time.h> |
支持系统时间函数 |
<complex.h> |
支持复杂的算法 |
<fenv.h> |
给出浮点状态标记和浮点环境的其他方面的访问 |
<inttypes.h> |
定义标准的可移植的整型的类型名集合,也支持处理最大宽度整数的函数 |
<iso646.h> |
定义各种对应操作的宏(如&&和^) |
<stdbool.h> |
支持布尔数据类型,定义宏,该宏有助于与C++兼容 |
<stdint.h> |
定义标准的可移植的整型的类型名集合,该文件包含在<inttypes.h>中 |
<tgmath.h> |
定义一般类型的浮点宏 |
<wchar.h> |
支持多字节和宽字节函数 |
<wctype.h> |
支持多字节和宽字节分类函数 |
12.4重新定义库函数
第十二章 I/O函数
13.1clearerr
13.2fclose
13.3 feof
13.4 ferror
13.5fflush
13.6fgetc
13.7fgettpos
13.8fgets
13.9fopen
###新手,不喜勿喷