C复习手记(杂)

经过几天的整理,将C语言的大致重点整理了出来,还有一些像指针、文件操作、链表等一些算法的内容,后面以专题来整理。整理过程中如果有错误,欢迎指出,我们同学习,共进步!

实型常量有两种表现形式:

  1. 平常的小数12.5;
  2. 传说中的指数形式0.125e2,但是指数形式表达需要注意,e或E的前面必须要有数字,且e或E后面的数字必须为整数;

转义字符:

字符常量有一类特殊形式的字符,它们就是转义字符,每个转义字符代表不同的含义,占一个字节的空间:

\a 响铃(BEL) 007 
\b 退格(BS) 008 
\f 换页(FF) 012 
\n 换行(LF) 010 
\r 回车(CR) 013 
\t 水平制表(HT) 009 
\v 垂直制表(VT) 011 
\\ 反斜杠 092 
\? 问号字符 063 
\' 单引号字符 039 
\" 双引号字符 034 
\0 空字符(NULL) 000 
\ooo 任意字符 三位八进制 
\xhh 任意字符 二位十六进制

注意不要将字符常量与字符串常量弄混,‘’之间只能包含一个字符,字符串常量末尾会自动加上一个“\0”表示字符串结束,所以“Hello”其实是六个字符;

符号常量用#define定义,将一个常量用一个符号来表示,符号常量一般用大写表示,不占用存储空间;

#define PI 3.1415926        //注意没有分号

常变量用count声明;

count int a = 3.14;

常变量与符号常量的区别是:两者的值都是不能被改变的,符号常量是用#define定义的,是在预编译的时候就将程序中对应的符号常量全部替换成对应的值,所以说符号常量在预编译之后就不存在了,故不占用存储空间,而常变量还是存在于存储单元中的,可以被调用,常量是没有名字的不变量,而常变量是有名字的不变量
常变量与变量之间的区别是:两者都是变量,都有类型,占空间,只是常变量不允许更改其值,这个专门为不能改其值,而又要重复调用的值准备的;符号常量、常变量和变量三者各有各的用处;

数据类型占空间问题

对于数据类型所占空间问题,不同的编译器对其是有不同的定义的,如Turbo C为每个INT 类型的变量分配了两个字节,而VC6.0则为INT类型的变量分配了4个字节,我们可以用sizeof(数据类型)来查看每个数据类型所占用的空间;
小技巧:当我们用malloc分配空间时,可以直接用sizeof(数据类型)*数据个数的方式来分配空间;

变量其实就是拿一个符号表示一个存储空间的地址,就像是把一个房间号取了一个名字,我们问张三的房子就可以知道在哪里了;

unsigned表示无符号的整型(包括字符型),特别是某些没有正负数概念的环境,我们可以直接用无符号整型,这样可以增加我们的存储范围;当我们输出整型数据的时候,要用“%u”的格式来进行输出;

变量命名规则:

在C语言中,认为大写字母和小写字母是两个不同的字符,标识符一般由字母、数字和下划线组成,只能由字母或者下划线开头;

多数的C编译器采取向零取整的方法;

%运算符

要求参与运算的对象都是整数,除了%运算符以外的运算符操作数可以是任何算术类型;

+=运算符

这是C语言中一种简便的写法,+=等价于name = name + num,举个栗子:

int i = 12;
i += 4;
//运算完毕后,i = 16,即i = i + 4;

相对应的就还有-=、*=、/=、%=等等,这就是我们写程序时的一个小技巧;

自增、自减运算符

i++ //我们先用这个数,在用完之后i自动加上1
i-- //同样的,在用完这个数后,给它减去1
++i //我们先给它加上一个1,然后我们再使用这个数
--i //同理

举个栗子:

for(i = 0;i < 10,i++)
    printf("%d",i);
//这样就会依次打印出0~9

在使用自增、自减运算符的时候,注意添加括号,避免i+++j的存在;

强制类型转换

不同的数据类型的数据之间可以进行混合运算,必要的时候可以用(类型名)(表达式)进行强制类型转换,有些时候我们也会预防报错,使程序更加规范,给它加上前缀;

举个栗子:

char a = 'A';
int b = 97;
b -= (int)a;     //这就是混合运算

int *i;
i = (int *)malloc(sizeof(int)*10); 

空语句

空语句可以作为延时的循环语句体来使用,也可以作为流程的转向点来使用;

三目运算符( ? : )

三目运算符也是C语言中的一个小技巧,他就是一个缩减版的if…else…,表达式规则:条件?表达式:表达式;

举个栗子:

(i == 5)? return 5; : return -1;
//等价于:
if(i == 5)
    return 5;
else
    return -1;

活用复合运算符、三目运算符可以提高程序的效率和美观性,减少程序大小;

混合运算之后,数据类型走向

在运算过程中,如果有int、float、double三种数据类型,那么最后结果是什么数据类型呢?
答案是:double,当不同数据类型的数据进行运算时,最后结果会朝着范围大的数据类型发展;

预编译、编译、链接操作

我们都知道,在C语言中,我们编译一个文件,有这么几部:预编译、编译、链接、生成可执行文件;

C语言本身不提供输入输出语句,我们使用的printf、scanf、getchar是函数库中提供的一些函数供我们调用,我们在调用他们的时候,一定要先预编译他们的函数库头文件;

在预编译的时候,是由预编译器进行操作的,他的任务就是将程序中涉及到的函数从头文件中提取出来,添加到主文件中,然后将一个跟编译无关的数据全部去掉,如注释等;

在编译的时候,并不是编译完了,程序就可以执行了,在编译器编译完成之后,它并不是一个整体,而是由一个一个函数所构成的程序碎片;

在链接的时候,由链接器完成,在这一步,我们将所有的.o文件整合在一起,构成每一块的对应关系,这样一来,就相当于把碎布缝了起来,就可以使用了;

输出限定小数位数

当我们输出数值的时候,我们都要限定小数的位数,这时候可以在格式字符前面加m.n,m表示输出的列数是m位,其中有n位是小数。如果你想保留7位小数,你可以这么输出——printf(“%10.7f”,a);
如果指定列宽,显示列数小于指定列数,那么默认右对齐,不足位由空格填补。如果想要左对齐显示,在m.n前面加个-即可;

对于选择语句和循环语句的嵌套问题,层次清楚,擅用{}会减少很多麻烦;

switch语句表达式:

switch(表达式)
{
    case 常量1:语句1;
    case 常量2:语句2;
    ……
    default:语句n;
}

while循环语句

while语句循环分为前测while循环和后测while循序,后测while循环至少执行一次程序体里面的语句;while语句一般用作不知道具体循环次数的循环操作;

表达式规则:

//前测型
while(条件)
{表达式}

//后测型
do
{表达式}while(条件)

举个栗子:

int i = 1;
while(i != 0)
{
    printf("i = %d",i);

}

for循环

对于for循环语句,主要针对已知循环次数的情况,当然for语句和while语句可以互相转换;
for循环的三个表达式原则上都可以省略,以实现不同的效果,如果三个表达式都省略,那个循环将会无终止的执行下去,这种方法在单片机中常用,用于无限循环这一段代码;

break语句用于提前终止循环;
continue语句用于提前结束本次循环;
return语句用于提前终止当前函数;

字符串初始化操作

对于字符串来说,我们可以将他们看做是一个数组,且这个数组一定有一个”\0”作为字符串结束的标志,如果数组中有多个”\0”,以最前面的”\0”为准;

这里我们就可以提一个小技巧了,我们在给字符串初始化的时候,我们经常char text = {“”};,其实我们只要把第一个字符写入’\0’就可以了,这样系统在识别的时候,发现第一个字符就是结束符,就默认字符串已经初始化了;

可用输出整数数值的方式,输出字符串,那么就可以显示字符串起始位置的地址,当然通过指针也可以得到;

strcat():字符串连接函数,将字符串2接在字符串1后面
strcpy()和strncpy():字符串复制函数,将字符串2复制到字符数组1中;strncpy()是将字符串2中的前N个字符复制到字符串数组1中;
注意:不能用赋值语句将一个字符常量或字符数组直接赋值给一个字符数组
strcmp():字符串比较函数,将字符串1和字符串2自左向右逐个字符进行比较,相等则返回0,字符串1>字符串2则返回一个正整数,反之返回一个负整数;
strlen():测试字符串的长度,注意不包括”\0”;
strlwr():转换为小写字母;
strupr():转换为大写字母;

工程管理

对于一个庞大的项目工程来说,一般不把所有的内容都放在一个源文件中,而是每个源文件作为实现某个功能的一个模块,由若干模块实现整体的效果,这样便于我们的编写和调试;同理就是说,一个源文件可以别多个程序所调用;

所有的函数都是相互独立的一个关系,故不存在嵌套定义函数的方式,我们就可以相互调用,但是我们不能调用main函数,这是被操作系统调用的;

函数

在C语言中,最小的基本单位就是函数,我们把一个函数看为一个独立的整体,他可以完成某项特定的动作。从函数时候有传参来看,可以将函数分为有参函数和无参函数,对于main函数来说,他是个无参函数,也可以是一个有参函数(后面会独立一个专题出来讲),但是他有返回值,它返回的是0,我们在有的程序中会看见,void main()这样的书写方式,这样问题不大,程序也可以正常运行,但是”return 0”的作用是当程序正常运行结束之后返回0,给系统一个信号,说明我已经正常运行结束了,如果没有的话,当程序出错时,可能表面并没有现象,但是出现的结果就是有问题的,你自己都不知道问题在哪里,所以,一般我们这样”int main(void)”来写,结尾时用”return 0”返回结束信号;

我们在定义函数时,括号中的参数我们称之为形式参数;在主调函数调用一个函数时,函数后面括号中的参数我们称之为实际参数;实参和形参的数据类型应该是相同的,当函数调用完毕后,形参的存储单元将会被释放;

return语句其一的作用就是返回函数的结果,即返回返回值。一般来说,返回值的类型应该和定义函数的类型是相同的;

函数的声明和调用

我们一般将自己定义的函数写在main函数的后面,这是我们需要在main函数的前面或者main函数体中先声明函数,然后再调用函数,不然可能会出现问题;

我们在调用函数的过程中,可能会直接或间接的调用函数本身,这种函数的调用,我们称之为递归调用(详见专题);

我们可以将数组作为函数的参数传参给函数进行处理,在定义函数时,数组形参可以不指定大小;

.text段、.data段和.bss段

每一个变量和函数都有两个属性,一个是数据类型,另外一个就是数据的存储类型,我们将存储类型分为4种:自动(auto)、静态(static)、寄存器(regi)、外部(extern);内存中供我们使用的空间大致可以分为三种:程序区、静态存储区、动态存储区
我们默认的就是自动存储类型,它们自动分配存储空间(故相同名字的变量,每次的存储地址都不相同),当我们调用完或者说函数结束后,存储空间就会被释放;

静态局部变量是存在于静态存储区的数据,在程序的整体执行过程中,都不回被释放,但他只是不被释放而已,还是可以对他的值进行修改的;如果在定义的过程中,我们没有对他们进行赋值的话,编译时会自动赋初值0或者空字符”\0”;虽然说变量没有被释放,但是它终究是局部变量,别的函数还是无法调用他的;

寄存器变量(可以不关注,因为现在编译系统可以自动识别使用频繁的变量,不需要我们特意指定了)

详细的我们独立一个专题出来讲;

结构体

我们有时为了反映相互独立的变量他们之间的内在联系,我们将多个数据类型复合起来,组成一个数据类型,这就是我们的结构体类型;

定义:
struct 结构体名
{成员列表(类型名 成员名)}结构体变量名;

我们将结构体定义好后可以直接定义结构体变量,就是上面这种方法,我们还可以像一般定义变量那样:struct 结构体名 结构体变量名;

结构体其实和我们一般的变量的定义等操作,都是类似的,唯一不同的是我们对其的赋值和调用,因为结构体中由多个变量组成,所以我们在调用的时候,要指明是哪个结构体变量的哪个值;

调用的方法:
结构体变量名.成员变量名

在所有运算符中,’.’运算符的优先级别是最高的,当我们面临结构体成员变量本身有属于一个结构体类型,我们在进行操作时,只能对最低级别的成员变量进行操作;

同类型的结构体之间可以相互赋值,但是,我们在输出的时候,不能直接”printf(“a.a = %d\na.b = %d\n”,a);”,正确的是:printf(“a.a = %d\na.b = %d\n”,a.a,a.b);

同样的,结构体也有指针,我们在定义的时候跟一般变量的方法相同,我们在调用的时候,是这样的:(*a).a,或者我们可以写成a->;

数据结构

数据的存储方式有很多种,像我们的数组就是按顺序存储的存储方式,但是一旦数组所需要的空间很大,或者说,我们内存连续的存储空间很小,达不到要求的时候,数组就显得不够用了,我们可以用结构体用链表的方式实现随机存储,可以更好结束大数据量的问题,两种方式各有好处,数组寻找数据的速度就比链表要快很多;后续会讲链表的创建方法;

刚才讲了结构体,还有一种数据结构跟结构体很像——共用体,相比而言他们的区别是:结构体是:把不同类型的数据组合成一个整体,他们各自都有一块存储空间;而共用体是使几个不同类型的变量共占一段内存,只能有一个变量存在(相互覆盖);定义:union 共用体名{成员列表(类型名 成员名)}共用体变量名;结构体和共用体的定义、声明基本相同;

如果你想限定某个变量的值,你可以用枚举将所有的可能性都列举出来,定义:enum 枚举名{枚举元素列表}枚举变量名;其实我们在给枚举定义的时候,编译器默认将枚举的成员列表进行编号,第一个成员是0,第二个是1,以此类推,所以枚举元素可以拿来做判断比较;

有些类型形式复杂,理解困难,容易写错,这是我们可以用typedef声明新的类型名;声明方法:typedef 原类型名 新类型名;

typedef和define的区别我们专题再讲;


未尽之处我会继续添加,一些大题我会做专题写一下,欢迎大家指出错误,如有雷同,不甚荣幸;一步一享受,同学习共进步!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值