近日重读谭浩强的《C程序设计》一书。由于长时间不用,不少琐碎的知识点已经忘记。在重读的过程中对知识点重新做了梳理,对于一些个人容易忽略和重要的知识点罗列出来,以便日后复习和快速回忆。
1. C语言提供的数据类型
a. 基本类型:整型(int),字符型(char),浮点型(单精度,双精度)
b. 构造类型:数组类型,结构体类型,共用体类型
c. 指针类型
d. 空类型
2. C语言中,采用符号定义常量,采用大写字母表示。例如:#define PRICE 35
3. 变量代表内存中具有特定属性的内存单元。变量名用小写字母表示,代表变量值在内存中的存储地址。变量需要先声明后使用。
4. 数值在内存中的存储形式是以补码表示的,求负数补码的方式是:将该数的绝对值的二进制形式取反,再加1。无符号数和长整型数在定义时,需要在后面加上U和L。
5. 浮点型数据在内存中按指数形式存储。在编译系统中,将浮点常量作为双精度处理,然后再根据赋予变量的类型,截取实型常量相应的有效数字。
6. 字符常量用单引号括起来。字符变量只能存放一个字符,不能存放字符串。在所用的编译系统中规定以一个字节来存放一个字符。由于字符变量以ASCII码形式存放在内存中,所以就使得字符变量与整型变量通用。既可以以字符型输出,又可以一整数形式输出。
7. 字符串常量与字符常量的差别在于,系统对字符串常量的最后以后字符后面加上"\0"表示结束。
8. 不同数据类型之间可以混合运算,不同类型的数据转换成同一类型。字符数据,短整型转换为整型,浮点型转换为双精度型。
9. 算术表达式的运算顺序先按运算符的优先级,再按从左至右的顺序。自增自减运算符的结合方式是自右至左。
- int i=3;
- printf("%d",-i++);
- printf("%d",i);
-
-
|
10. 赋值表达式的求解过程:先求赋值表达式右侧表达式的值,然后赋值给赋值运算符左侧的值。左值只能是变量。
- int a=12;
- a+=a-=a*a;
- prinf("%d",a);
-
|
11. 逗号表达式:表达式1,表达式2。先求解表达式1的值,再求解表达式2的值。整个表达式的值是表达式2的值。在所有运算符中,级别最低。
二、顺序、选择程序结构以及循环控制
1. C标准库将一些常用的函数的放在其中,并已编译成为目标文件,在连接时直接使用,可以减轻C语言的编译负担。
2. 不同运算符的优先级(从高到低):非,算术运算符,关系运算符,赋值运算符。
3. 关系表达式的值是一个逻辑值,C语言中没有逻辑变量和逻辑常量,以1代表真,0代表假。例如:f=a>b>c,先执行a>b,即1>c,所以f=0。
4. 条件运算符的一般形式:表达式1?表达式2:表达式3。结合方向自右向左,优先级低于算术符和关系运算符。
5. 选择,循环结构的几种典型的语句这里不做赘述。具体参看课本。
三、函数和预处理命令
1. 主函数调用其它函数,其它函数也可以相互调用。
2. 如果在函数定义时不指定函数类型,系统会隐含指定其为整型。
3. 定义函数时,括号中的为形参。调用函数时,括号中的为实参。在函数被调用时,形参获得内存单元,在调用结束后释放内存。实参仍然保留并维持原值,形参的变化并不会影响实参。
4. 如果函数中,return语句返回,类型与函数类型不一致,以函数类型为准。
5. 如果使用用户自己定义的函数,而该函数的位置在主调函数之后,则需要在主调函数中作声明。声明可以不写形参名,只写类型。函数类型,函数名,参数个数,参数类型以及参数的顺序必须保持一致。
6. 变量的分类:从作用范围划分:
局部变量:函数中定义,形参,复合体中。在局部变量的作用范围内,外部同名 变量被屏蔽。
全局变量:函数外定义,有效范围是从定义处到文件结束。执行过程中始终占据 内存。
从声明周期划分:
auto:没有经过static声明的局部变量和形参,系统隐含将其定义为auto类型, 表示动态分配内存空间;
static:如果希望局部变量的值在下次调用时保存,可将该变量声明为static。 静态变量在编译时赋初值,而对于动态变量来说,如果不对其赋初值,它的值会是 一个不确定的值。另外,使用static声明外部变量,说明该变量只能供本文件使用。
register:用于声明寄存器变量。只能用于局部自动变量和和形参。
extern:两个作用:
(1)扩展外部变量的作用范围;
(2)使用其他文件中的外部变量前声明,表示本文件中出现的extern声明变量 已经在其他文件中定义,本文件不需要为其分配内存。改变影响另外一个文件中该 变量的执行。
7. 内部函数:定义函数时,前面加static,表示只能供本文件中的函数使用。
外部函数:可以供外部文件中使用的函数。在函数最左边加上extern。不加该关键字,系统隐含处理为外部函数。另外,在调用该函数的外部文件中,对该被调用函数声明时,须加上该关键字。可以理解为将函数的作用范围扩展到该文件中。
8. 预处理命令,是指在编译之前,首先对预处理语句进行处理,,使得文件中不再包含预处理命令,然后统一编译。
9. 宏定义:#define PI 3.1415926
#define S(a,b) a*b
宏名用大写表示,仅作简单置换,不做正确性检查。双引号的部分不做置换。
10. 文件包含:#include <文件名> 系统优先
#include "文件名" 用户优先
11. 条件编译:对指定语句进行编译。有以下三种形式:
- #ifdef PRINT
- printf("");
- #else SCANF
- scanf("%d",&a);
- #endif
-
-
- #ifndef PRINT
- printf("");
- #else SCANF
- scanf("%d",&a);
- #endif
-
-
- #if PRINT
- printf("");
- #else SCANF
- scanf("%d",&a);
- #endif
-
|
四、 数组和指针
1. 不允许对数组的大小作动态定义,数组的大小不依赖于程序运行过程中变量的值。在定义时,需要指明数组元素的个数。可以全部赋值(无需指明数组元素的个数),也可以部分赋值。未赋值部分填充0。
2. 二维数组可以被认为是元素为一维数组的一维数组。首先存放第一行元素,再存放下一行元素。在定义时,既可以部分定义,也可以全部定义。在全部定义时,第一维的长度可以不指定,但第二维的长度不能省。
3. 字符数组中的元素是一个字符。字符串作为字符数组来处理。系统将字符串常量末尾自动加上一个"\0"作为结束符,由此作为结束的标志。
- char c[]="love";
- char c[]={"love"};
- char c[]={'l','o','v','e','\0'};
-
|
4. 字符串输出的两种形式
-
- for(i=0;i<10;i++)
- printf("%c",c[i]);
-
-
- printf("%s",c);
|
5. 指针是地址,指针变量是存放指针的变量。
6. int p=3;int *pi=&p;
p:3
&p:p的地址
pi: p的地址
*p:p的内容,就是3.
7. 指针变量作为函数参数,可以实现在函数中改变实参的值。因为将指针变量传进函数以后,形参和实参都是指向同一变量的指针。
8. 数组名代表数组首元素的地址。因此可以把数组名直接赋值给一个指针变量而无须加上取地址符号。数组名是一个常量,不能对其进行运算和改变。
9. 指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价。
10. 数组名作为函数参数,形参数组各元素的变化会引起实参数组的变化。实际上,编译器将形参中的数组名当做指针变量来处理。
11. 对于二维数组,数组名是第一行(一个一维数组)的地址。加上指向符号(或者a[i])后,则是其包含的一维数组的首元素的地址。a,*a和a[0]指向的是同一个地址。但是包含的意义不同。在指向行的指针前面加上指向符号,就转换为指向列的指针。
12. 指针可以指向一个字符串,实际上是把字符串的首元素地址赋值给指针变量。
13. 使用数组名输出的只能是字符串数组。可以用%s对字符串进行整体输出。
14. 指向函数的指针:int (*p)(int,int);
返回指针值的函数:int *p();
指针数组:int *p[4]
指向指针的指针:int **p;
五、结构体与共用体
1. 结构体的声明和定义
- struct student {
- int id;
- char name[20];
- int age;
- }student1,student2;
|
2. 结构体类型与变量:
a. 只能对变量操作而不能对类型进行操作;
b. 对结构体中成员可以单独使用。变量名.成员名;
c. 成员也可以式结构体类型;
3. 结构体变量可以在定义时赋初值:
- struct student {
- int id;
- char name[20];
- int age;
- }student1={1010,"liming",25};
|
4. 结构体数组的定义和赋值:
- struct student {
- int id;
- char name[20];
- int age;
- };
- struct student stu[3];
|
5. 指向结构体的指针
- struct student {
- int id;
- char name[20];
- int age;
- }stu_1;
- struct student * p;
- p=&stu_1;
-
- p->id=101010;
|
6. 共同体类型的声明定义和引用
共同体类型中的变量起始地址一致,只有一个成员瞬时起作用,同一个成员最后一个变量起作用。
- union data{
- int i;
- char ch;
- float f;
- }a;
-
- a.i=15
- a.ch='a';
- a.f=1.5
|
7. 使用tyepdef声明新的类型名代替已有的类型名步骤:
a. 写出定义体:int i
b. 将变量名替换成为自定义名:int INT
c. 加上typedef关键字:typedef int INT
六、位运算
1. 位运算只能是整型或者字符型数据,不能是实型。
2. 常用的位操作:
&: 清零,取一个数的某些位
|: 置1
^: 同号为0,异号为1。用于特定位翻转(^1),保留原值(^0)
~: 取反
<<: 溢出舍去,空缺补零
>>:溢出舍去,无符号空缺补零;有符号不定。
3. C语言允许在一个结构体数据类型中以位为单位来指定其成员所占的长度。以位为单位的成员成为成为位段。
- struct data{
- unsigned a:2;
- unsigned b:2;
- unsigned :0;
- unsigned :2;
- unsigned c:3;
- int i;
- };
-
-
-
-
|