1.本篇目的:搭建并完善C知识体系
2.本篇的结构
- 第一部分:基础点
- 第二部分:调试技巧
第一部分:基础点
预处理器
#include指令:文件包含,该指令所在的行都将被替换为由文件名指定的文件的内容,一种将所有声明捆绑在一起的较好的办法,保证所有的源文件有相同的定义与变量声明
#include “文件” :先在源文件所在位置查找该文件,如果在该位置未找到,再根据相应规则查找
#include <文件> :根据相应规则查找
#define指令:宏替换,#define 名字 替换文本
宏
:将函数定义为宏可避免调用函数时所需的运行时开销
变量存储类别
静态存储方式 程序运行期间分配固定的存储空间的方式。静态存储区中存放了在整个程序执行过程中都存在的变量,如全局变量。 动态存储方式 指在程序运行期间根据需要进行动态的分配存储空间的方式。动态存储区中存放的变量是根据程序运行的需要而建立和释放的,通常包括:函数形式参数;自动变量;函数调用时的现场保护和返回地址等。 类型 作用域 存储位置 生命周期 特点 实例 static静态变量 所在文件,准确地说作用域是从定义之处开始,到文件结尾处结束(static 全局变量)、 所在函数(static 局部变量) 定义后一直占据存储空间,内存的静态区 程序运行期间 只被初始化一次(程序执行前,编译时),即使函数被调用多次,该变量的值也不会重置,初始化表达式是常量表达式,没有初始化表达式的元素被初始化为0或空字符 void func1(void) { /* ‘thingy’ 是 ‘func1’ 的局部变量 - 只初始化一次 * 每次调用函数 ‘func1’ ‘thingy’ 值不会被重置。 */ static int thingy=5; thingy++; printf(“ thingy 为 %d , count 为 %d\n”, thingy, count); } thingy 为 6 , count 为 9 thingy 为 7 , count 为 8 thingy 为 8 , count 为 7 thingy 为 9 , count 为 6 thingy 为 10 , count 为 5 thingy 为 11 , count 为 4 thingy 为 12 , count 为 3 thingy 为 13 , count 为 2 thingy 为 14 , count 为 1 thingy 为 15 , count 为 0 register 定义存储在寄存器中而不是 RAM 中的局部变量 、函数形参(局部静态变量不能定义为寄存器变量) 定义 ‘register’ 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制 1.访问速度更快,在需要频繁访问的变量上使用 register 存储类可以提高程序的运行速度 2.变量的最大尺寸等于寄存器的大小(通常是一个字),且不能对它应用一元的 ‘&’ 运算符(因为它没有内存位置)即不能直接取地址 { register int miles; } 外部变量external 外部变量的意义是某函数可以调用在该函数之后定义的变量。或定义在其他文件中声明的全局变量或函数,当使用 extern 关键字时,不会为变量分配任何存储空间,而只是指示编译器该变量在其他文件中定义 1.只被初始化一次(程序执行前),初始化表达式必须是常量表达式,没有初始化表达式的元素被初始化为0;2.通常用于当有两个或多个文件共享相同的全局变量或函数的时候 #includ <stdio.h> int main() { //定义外部局部变量 extern int x; return 0; } int x=100; 自动变量auto 仅函数内部,所有局部变量默认的存储类 函数被调用期间,在函数开始时被创建,在函数结束时被销毁 每次进入函数或程序块都初始化,没有初始化表达式的元素被初始化为0 { int mount; auto int month; } 函数
函数 形式 说明 内部函数(静态函数) static [数据类型] 函数名([参数]) 不能被其他源文件调用的函数称为内部函数 ,static是对函数的作用范围的一个限定,限定该函数只能在其所处的源文件中使用,因此在不同文件中出现相同的函数名称的内部函数是没有问题的。 外部函数 extern [数据类型] 函数名([参数]) 能被其他源文件调用的函数称为外部函数,C语言规定,在没有指定函数的作用范围时,系统会默认认为是外部函数,因此当需要定义外部函数时extern也可以省略。 extern可以省略; 指针
运算符&:取地址,只能应用于内存中对象,即变量与数组元素,不能作用与表达式、常量、或register变量
运算符:间接寻址或间接引用运算符,作用于指针时,将访问指针所指向的对象。
&、优先级高于算术运算符
指针变量可以相互赋值,指向相同的对象- 1)指针与数组 :
一般,指针编写的程序比用数组下标编写的程序执行速度快
一个通过数组和下标实现的表达式可等价地通过指针和偏移量实现char s[] == char *s 、&a[2] == a+2 (a数组)
2)特性
- 某些情况下对指针进行比较运算(如指针p、q指向同一个数组的成员)
- 指针可以和整数相加或相减
- 指针的算术运算具有一致性:所有的指针运算都会自动考虑它所指向的对象的长度
- 有效的指针运算:
- 相同类型指针之间赋值运算
- 指针同整数之间的加法减法
- 指向相同数组中元素的两个指针间的减法和比较运算
- 指针赋值为0或指针与0之间的比较运算
3)指针数组、指针的指针
- 如char *lineptr[10]
- 初始化:如,static char *name[] = {“xiaoming”,”xiaoqiang”}
- 指针数组优点:数组的每一个元素的长度可以不同
- 如char *lineptr[10]
4)函数指针
K&R P99
运算符优先级
1)优先级1:数组下标[],圆括号( ),成员选择(对象).,成员选择(指针)->
结合方向为左到右
2)优先级2:负号运算符-,强制类型转换,自增运算符++,自减运算符–,取值运算符,取地址运算符&,逻辑非运算符!,按位取反运算符~,长度运算sizeof符,结合方向为右到左
3)优先级3:除/,乘*,余数%,结合方向为左到右
4)优先级4:加+,减-,结合方向为左到右
5)优先级5:左移<<,右移>>,结合方向为左到右
6)优先级6:大于>,大于等于>=,小于<,小于等于<=,结合方向为左到右
7)优先级7:等于==,不等于!=,结合方向为左到右
8)优先级8:级别先后为,按位与&,按位异或^,按位或| ,逻辑与&&,逻辑或|| 条件运算符?:,注意得是条件运算结合方向为右到左
9)优先级9:赋值运算符=,除后赋值/=,乘后赋值*=,取模后赋值%=,加后赋值+=,减后赋值-=,左移后赋值<<=,右移后赋值>>=,按位与后赋值&=,按位异或后赋值^=,按位或后赋值|=,结合方向为右到左
结构
struct point {
int x;
int y;
};
声明:struct {int x,int y} x,y,z; #分配存储空间
struct point pt;
初始化:
struct point maxpt = {320, 200};
成员:maxpt.x
maxpt.y
嵌套:
struct rect {
struct point pt1;
struct point pt2;
};
struct rect screen;
- 成员: screen.pt1.x
合法操作:
1.作为一个整体赋值和赋值
2.通过&取地址
3.访问其成员
结构指针:
struct point *ptrstr;
ptrstr -> x
结构数组
1 | struct key { |
};
- 结构指针
- 关键字统计
自引用结构
K$R P116 ex:统计输入所有单词出现频次(二叉树)
表查找
- 类型定义(typedef)
- 联合
- 位字段
命令行参数
1
2
3
4
5
6
7
8
9
10
int main(int argc, char *argv[] )
{
#./test -x 注意优先级顺序
printf("%s\n",argv[0]);#./test
printf("%c\n",(*++argv)[0]);#- argv指向argv[1]
printf("%c\n",*++argv[0]);
printf("%d\n",argc);#2
}运算符集合
控制流语句
标准库
输入输出:printf (“%d”,i)、scanf(“%d”,&i)
文件访问:
1.打开文件,返回文件指针
1
2
3FILE *fp;
FILE *fopen(char *name,char *mode)
fp = fopen(name,mode)
1 | 2.文件读写 |
1 | int fscanf(FILE *fp, char *format, ...) |
1 | 3.关闭文件 |
第二部分:调试技巧
1 |
|