C语言基础学习笔记.docx
- 文档编号:28850133
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:17
- 大小:27.45KB
C语言基础学习笔记.docx
《C语言基础学习笔记.docx》由会员分享,可在线阅读,更多相关《C语言基础学习笔记.docx(17页珍藏版)》请在冰豆网上搜索。
C语言基础学习笔记
一:
程序设计与算法
对于理工科的大学生而言,掌握一门高级语言及其基本的编程技能是必需的。
大学学习,除了掌握本专业系统的基础知识外,科学精神的培养、思维方法的锻炼、严谨踏实的科研作风养成,以及分析问题、解决问题的能力的训练,都是日后工作的基础。
学习计算机语言,正是一种十分有益的训练方式,而语言本身又是与计算机进行交互的有力的工具。
C语言之所以被称为中级语言,是因为它把高级语言的成分同汇编语言的功能结合起来了。
1.1结构
C语言是块结构(block-structured)语言,但是它还是常被称为结构化语言。
这是因为它在结构上类似于ALGOL、Pascal和Modula-2(从技术上讲,块结构语言允许在过程和函数中定义过程或函数。
用这种方法,全局和局部的概念可以通过“作用域”规则加以扩展,“作用域”管理变量和过程的“可见性”。
因为C语言不允许在函数中定义函数,所以不能称之为通常意义上的块结构语言)。
结构化语言的显著特征是代码和数据的分离。
这种语言能够把执行某个特殊任务的指令和数据从程序的其余部分分离出去、隐藏起来。
C语言的主要结构成分是函数C的独立子程序。
在C语言中,函数是一种构件(程序块),是完成程序功能的基本构件。
函数允许一个程序的诸任务被分别定义和编码,使程序模块化。
函数的基本形式是:
函数类型函数名(形式参数)
形式参数说明;
{
数据说明部分;
语句部分;
}
其中:
函数头 包括函数说明、函数名和圆括号中的形式参数(如intvolume(a,b,c)),如果函数调用无参数传递,圆括号中形式参数为空(如voidproc()函数)。
形式参数 指定函数调用传递参数的数据类型(如例1.3中语句inta,b,c;)。
函数体 包括函数体内使用的数据说明和执行函数功能的语句,花括号{和}表示函数体的开始和结束。
开发一个C程序,包括以下四步:
1)程序设计程序设计亦称程序编辑。
程序员用任一编辑软件(编辑器)将编写好的C程序输入计算机,并以文本文件的形式保存在计算机的磁盘上。
编辑的结果是建立C源程序文件。
C程序习惯上使用小写英文字母,常量和其他用途的符号可用大写字母。
C语言对大、小写字母是有区别的。
关键字必须小写。
2)程序编译编译是指将编辑好的源文件翻译成二进制目标代码的过程。
编译过程是使用C语言提供的编译程序(编译器)完成的。
不同操作系统下的各种编译器的使用命令不完全相同,使用时应注意计算机环境。
编译时,编译器首先要对源程序中的每一个语句检查语法错误,当发现错误时,就在屏幕上显示错误的位置和错误类型的信息。
此时,要再次调用编辑器进行查错修改。
然后,再进行编译,直至排除所有语法和语义错误。
正确的源程序文件经过编译后在磁盘上生成目标文件。
3)链接程序编译后产生的目标文件是可重定位的程序模块,不能直接运行。
链接就是把目标文件和其他分别进行编译生成的目标程序模块(如果有的话)及系统提供的标准库函数链接在一起,生成可以运行的可执行文件的过程。
链接过程使用C语言提供的链接程序(链接器)完成,生成的可执行文件存在磁盘中。
4)程序运行生成可执行文件后,就可以在操作系统控制下运行。
若执行程序后达到预期目的,则C程序的开发工作到此完成。
否则,要进一步检查修改源程序,重复编辑—编译—链接—运行的过程,直到取得预期结果为止。
大部分C语言都提供一个独立的开发集成环境,它可将上述四步连贯在一个程序之中。
1.2算法:
什么是程序?
程序=数据结构+算法。
程序设计的关键之一,是解题的方法与步骤,是算法。
学习高级语言的重点,就是掌握分析问题、解决问题的方法,就是锻炼分析、分解,最终归纳整理出算法的能力。
与之相对应,具体语言,如C语言的语法是工具,是算法的一个具体实现。
所以在高级语言的学习中,一方面应熟练掌握该语言的语法,因为它是算法实现的基础,另一方面必须认识到算法的重要性,加强思维训练,以写出高质量的程序。
二:
数据类型、运算符和表达式
2.1数据类型
C语言有五种基本数据类型:
字符、整型、单精度实型、双精度实型和空类型。
C语言还提供了几种聚合类型(aggregatetypes),包括数组、指针、结构、共用体(联合)、位域和枚举。
为了使用方便,C编译程序允许使用整型的简写形式:
•shortint 简写为short。
•longint 简写为long。
•unsignedshortint 简写为unsignedshort。
•unsignedint 简写为unsigned。
•unsignedlongint 简写为unsignedlong。
即int可缺省。
2.2变量
在C语言中,标识符是对变量、函数标号和其它各种用户定义对象的命名。
标识符的长度可以是一个或多个字符。
绝大多数情况下,标识符的第一个字符必须是字母或下划线,随后的字符必须是字母、数字或下划线(某些C语言编译器可能不允许下划线作为标识符的起始字符)。
字符常量是指用一对单引号括起来的一个字符。
如‘a’,‘9’,‘!
’。
字符常量中的单引号只起定界作用并不表示字符本身。
单引号中的字符不能是单引号(’)和反斜杠(\),它们特有的表示法在转义字符中介绍。
在C语言中,字符是按其所对应的ASCII码值来存储的,一个字符占一个字节。
由于C语言中字符常量是按整数(short型)存储的,所以字符常量可以像整数一样在程序中参与相关的运算。
C语言中,字符串常量在内存中存储时,系统自动在字符串的末尾加一个“串结束标志”,即ASCII码值为0的字符NULL,常用\0表示。
因此在程序中,长度为n个字符的字符串常量,在内存中占有n+1个字节的存储空间。
其值可以改变的量称为变量。
一个变量应该有一个名字(标识符),在内存中占据一定的存储单元,在该存储单元中存放变量的值。
请注意区分变量名和变量值这两个不同的概念。
实型常量又称浮点常量,是一个十进制表示的符号实数。
符号实数的值包括整数部分、尾数部分和指数部分。
实型常量的形式如下:
[digits][.digits][E|e[+|-]digits]
在此digits是一位或多位十进制数字(从0~9)。
E(也可用e)是指数符号。
小数点之前是整数部分,小数点之后是尾数部分,它们是可省略的。
小数点在没有尾数时可省略。
C语言允许将程序中的常量定义为一个标识符,称为符号常量。
符号常量一般使用大写英文字母表示,以区别于一般用小写字母表示的变量。
符号常量在使用前必须先定义,定义的形式是:
#define<符号常量名>;<常量>;
#define是C语言的预处理命令,它表示经定义的符号常量在程序运行前将由其对应的常量替换。
字符变量用来存放字符常量,注意只能存放一个字符,不要以为在一个字符变量中可以放字符串。
2.3运算符
C语言有三大运算符:
算术、关系与逻辑、位操作。
移位操作可对外部设备(如D/A转换器)的输入和状态信息进行译码,移位操作还可用于整数的快速乘除运算。
如表2-9所示(假定移位时补0),左移一位等效于乘2,而右移一位等效于除以2。
反码操作符为~。
~的作用是将特定变量的各位状态取反,即将所有的1位置成0,所有的0位置成1。
位操作符经常用在加密程序中。
C语言提供了一个可以代替某些if-then-else语句的简便易用的操作符?
。
该操作符是三元的,其一般形式为:
EXP1?
EXP2:
EXP3
EXP1,EXP2和EXP3是表达式,注意冒号的用法和位置。
操作符“?
”作用是这样的,在计算EXP1之后,如果数值为True,则计算EXP2,并将结果作为整个表达式的数值;如果EXP1的值为Flase,则计算EXP3,并以它的结果作为整个表达式的值。
逗号操作符和标准英语的and是同义词。
2.4表达式
混合于同一表达式中的不同类型常量及变量,应均变换为同一类型的量。
C语言的编译程序将所有操作数变换为与最大类型操作数同类型。
变换以一次一操作的方式进行。
具体规则如下:
1)所有char及shortint型量转为int型,所有float转换为double。
2)如操作数对中一个为longdouble,另一个转换为longdouble。
① 要不然,一个为double,另一个转为double。
② 要不然,一个为long,另一个转为long。
③ 要不然,一个为unsigned,另一个转为unsigned。
一旦运用以上规则。
每一对操作数均变为同类型。
注意,规则2)有几种必须依次应用的条件。
可以通过称为cast的构成符强迫一表达式变为特定类型。
其一般形式为:
(type)expression
(type)是标准C语言中的一个数据类型。
为了增加可读性,可以随意在表达式中插入tab和空格符。
冗余的括号并不导致错误或减慢表达式的执行速度。
冗余的括号并不导致错误或减慢表达式的执行速度。
三:
程序控制语句
3.1程序的三种基本结构
C语言中,有一组相关的控制语句,用以实现选择结构与循环结构:
选择控制语句;if;
switch、case
循环控制语句:
for、while、do…while
转移控制语句:
break、continue、goto
3.2数据的输入与输出
最常用的输入输出函数有scanf()、printf()、getchar()和putchar()
%[<修饰符>;]<格式字>;
d 输入一个十进制整数
o 输入一个八进制整数
x 输入一个十六进制整数
f 输入一个小数形式的浮点数
e 输入一个指数形式的浮点数
c 输入一个字符
s 输入一个字符串
putchar()与getchar()是对单个字符进行输入输出的函数;
getchar()的功能是返回键盘输入的一个字符,它不带任何参数;
putchar()的作用是向屏幕上输出一个字符,它的功能与printf函数中的%c相当。
3.3循环控制语句
在循环语句中,break语句的作用是在循环体中测试到应立即结束循环时,使控制立即跳出循环结构,转而执行循环语句后的语句。
continue语句只能用于循环结构中,一旦执行了continue语句,程序就跳过循环体中位于该语句后的所有语句,提前结束本次循环周期并开始新一轮循环。
四:
函数
程序员在设计一个复杂的应用程序时,往往也是把整个程序划分为若干功能较为单一的程序模块,然后分别予以实现,最后再把所有的程序模块像搭积木一样装配起来,这种在程序设计中分而治之的策略,被称为模块化程序设计方法。
4.1函数说明与返回值
当一个函数没有明确说明类型时,C语言的编译程序自动将整型(int)作为这个函数的缺省类型,缺省类型适用于很大一部分函数。
当有必要返回其它类型数据时,需要分两步处理:
首先,必须给函数以明确的类型说明符;其次,函数类型的说明必须处于对它的首次调用之前。
当被说明为整型的函数返回字符时,这个字符值被转换为整数。
因为C语言以不加说明的方式进行字符型与整型之间的数据转换,因而多数情况下,返回字符值的函数并不是说明为返回字符值,而是由函数的这种字符型向整型的缺省类型转换隐含实现的。
返回语句return有两个重要用途。
第一,它使得内含它的那个函数立即退出,也就是使程序返回到调用语句处继续进行。
第二,它可以用来回送一个数值。
所有非空值的函数都会返回一个值。
大部分函数属于三种类型。
第一种类型是简单计算型—函数设计成对变量进行运算,并且返回计算值。
第二类函数处理信息,并且返回一个值,仅以此表示处理的成功或失败。
例如write(),用于向磁盘文件写信息。
如果写操作成功了,write()返回写入的字节数,当函数返回-1时,标志写操作失败。
最后一类函数没有明确的返回值。
实际上这类函数是严格的过程型函数,不产生值。
4.2函数的作用域规则
C语言中所有的函数都处于同一作用域级别上。
这就是说,把一个函数定义于另一个函数内部是不可能的。
全局变量和某一函数的局部变量同名时,该函数对该名的所有访问仅针对局部变量,对全局变量无影响.
动态存储变量可以是函数的形式参数、局部变量、函数调用时的现场保护和返回地址。
这些动态存储变量在函数调用时分配存储空间,函数结束时释放存储空间。
在编译时分配存储空间的变量称为静态存储变量,其定义形式为在变量定义的前面加上关键字“static”。
4.3函数的调用与参数
函数定义时填入的参数我们称之为形式参数,简称形参,它们同函数内部的局部变量作用相同。
形参的定义是在函数名之后和函数开始的花括号之前。
调用时填入的参数,我们称之为实际参数,简称实参。
一般说来,有两种方法可以把参数传递给函数。
第一种叫做“赋值调用”(callbyvalue),这种方法是把参数的值复制到函数的形式参数中。
第二种方法是“引用调用”(callbyreference)。
这种方法是把参数的地址复制给形式参数,在函数中,这个地址用来访问调用中所使用的实际参数。
这意味着,形式参数的变化会影响调用时所使用的那个变量。
切记,传给函数的只是参数值的复制品。
所有发生在函数内部的变化均无法影响调用时使用的变量。
4.4递归
如果函数内部一个语句调用了函数自己,则称这个函数是“递归”。
递归是以自身定义的过程。
也可称为“循环定义”。
4.5实现问题
有两个原因使得内嵌代码的执行速度比函数快。
首先,调用需要花费时间;其次,如果有参数需要传递,就要把它们放在堆栈中,这也要用时间。
4.6函数库和文件
一个函数设计完后,我们可以用三种方法处理它:
1)把它放在main()函数的同一个文件中;2)把它和写好的其它函数一起放在另一个文件中;3)把它放在函数库中。
在程序开发的早期做一点文件组织工作就可以避免这一问题。
首先可以把概念上有关的函数组织到一个文件中。
如果在编写正文编辑程序时,把删除正文所用的所有函数放进另一个文件,等等。
第二,把所有的通用函数放在一起。
例如,在数据库程序中,输入/输出格式编排函数是被其它函数调用的通用函数,应把它们放进一个单独的文件里。
第三,把最高层函数放进一个单独的文件中,如果空间允许,就和main()放在一起。
最高层函数被用来启动程序的总体活动。
这些例程从本质上定义了程序的操作
4.7C语言的预处理程序与注释
ANSI标准定义的C语言预处理程序包括下列命令:
#define 命令#define定义了一个标识符及一个串。
在源程序中每次遇到该标识符时,均以定义的串代换它。
ANSI标准将标识符定义为宏名,将替换过程称为宏替换。
该语句没有分号。
在标识符和串之间可以有任意个空格,串一旦开始,仅由一新行结束。
#error 强迫编译程序停止编译,主要用于程序调试。
#include 使编译程序将另一源文件嵌入带有#include的源文件,被读入的源文件必须用双引号或尖括号括起来。
#if #if的一般含义是如果#if后面的常量表达式为true,则编译它与#endif之间的代码,否则跳过这些代码。
命令#endif标识一个#if块的结束。
#else 功能有点象C语言中的else;#else建立另一选择(在#if失败的情况下)
#elif 与ELSEIF相同,它形成一个ifelse-if阶梯状语句,可进行多种编译选择。
#elif后跟一个常量表达式。
如果表达式为true,则编译其后的代码块,不对其它#elif表达式进行测试。
否则,顺序测试下一块。
#endif
#ifdef
#ifndef
#undef 取消其后那个前面已定义过有宏名定义。
#line 改变_LINE_与_FILE_的内容,它们是在编译程序中预先定义的标识符。
#pragma 为实现时定义的命令,它允许向编译程序传送各种指令。
可用#pragma语句指定一个跟踪选择。
五:
数组
5.1一维数组
将一维数组传递给函数时,把数组名作为参数直接调用函数即可,无需任何下标。
这样,数组的第一个元素的地址将传递给该函数。
C语言并不是将整个数组作为实参来传递,而是用指针来代替它。
一维数组的最普通的用法是作为字符串。
在C语言中,字符串被定义为一个以空字符终结的字符数组。
空字符以‘\0’来标识,它通常是不显示的。
因此,在说明字符数组时,必须比它要存放的最长字符串多一个字符。
尽管C语言并不把字符串定义为一种数据类型,但却允许使用字符串常量。
字符串常量是由双引号括起来的字符表。
例如,下面两个短语均为字符串常量:
"hellothere"
"thisisatest"
不必向字符串的末尾加空字符,C编译程序会自动完成这一工作。
5.2二维数组
二维数组以行—列矩阵的形式存储。
第一个下标代表行,第二个下标代表列,这意味着按照在内存中的实际存储顺序访问数组元素时,右边的下标比左边的下标的变化快一些。
可用二维字符数组的形式建立字符串数组,左下标决定字符串的个数,右下标说明串的最大长度。
5.3多维数组
关于多维数组,需要注意一点:
计算机要花大量时间计算数组下标,这意味着存取多维数组中的元素要比存取一维数组的元素花更多的时间。
由于这些和其它原因,大量的多维数组一般采用C语言动态分配函数及指针的方法,每次对数组的一部分动态地分配存储空间。
多维数组传递给函数时,除第一维外,其它各维都必须说明。
5.4数组的初始化
六:
指针
6.1指针与指针变量
变量a,b是整型变量,在内存各占2个字节;x,y是实型,各占4个字节;m是双精度实型,占8个字节;ch1,ch2是字符型,各占1个字节。
访问变量,首先应找到其在内存的地址,或者说,一个地址唯一指向一个内存变量,我们称这个地址为变量的指针。
如果将变量的地址保存在内存的特定区域,用变量来存放这些地址,这样的变量就是指针变量,通过指针对所指向变量的访问,也就是一种对变量的“间接访问”。
变量的地址就是指针,存放指针的变量就是指针变量。
6.2指针变量的定义与引用
利用指针变量,是提供对变量的一种间接访问形式。
对指针变量的引用形式为:
*指针变量
其含义是指针变量所指向的值。
6.3指针运算符与指针表达式
在C中有两个关于指针的运算符:
•&运算符:
取地址运算符,&m即是变量m的地址。
•*运算符:
指针运算符,*ptr表示其所指向的变量。
使用指针类型做函数的参数,实际向函数传递的是变量的地址。
由于子程序中获得了所传递变量的地址,在该地址空间的数据当子程序调用结束后被物理地保留下来。
6.4指针与数组
变量在内存存放是有地址的,数组在内存存放也同样具有地址。
对数组来说,数组名就是数组在内存安放的首地址。
指针变量是用于存放变量的地址,可以指向变量,当然也可存放数组的首址或数组元素的地址,这就是说,指针变量可以指向数组或数组元素,对数组而言,数组和数组元素的引用,也同样可以使用指针变量。
所以引用数组的时候可以用地址法和指针法。
6.4.1指针与一维数组
若ptr指向了一维数组,现在看一下C规定指针对数组的表示方法:
1)ptr+n与a+n表示数组元素a[n]的地址,即&a[n]。
对整个a数组来说,共有10个元素,n的取值为0~9,则数组元素的地址就可以表示为ptr+0~ptr+9或a+0~a+9,与&a[0]~&a[9]保持一致。
2)知道了数组元素的地址表示方法,*(ptr+n)和*(a+n)就表示为数组的各元素即等效于a[n]。
3)指向数组的指针变量也可用数组的下标形式表示为ptr[n],其效果相当于*(ptr+n)。
6.4.2指针与二维数组
对于二维数组a[n][m]:
a是二维数组的首地址,&a[0][0]既可以看作数组0行0列的首地址,同样还可以看作是二维数组的首地址,a[0]是第0行的首地址,当然也是数组的首地址。
同理a[n]就是第n行的首址;&a[n][m]就是数组元素a[n][m]的地址。
若赋值:
ptr=a;则用ptr++就能访问数组的各元素。
6.4.3数组指针作函数的参数
子程序的形式参数为一维数组,实际参数是指向一维数组的指针。
由于C程序的函数调用是采用传值调用,即实际参数与形式参数相结合时,实参将值传给形式参数,所以当我们利用函数来处理数组时,如果需要对数组在子程序中修改,只能传递数组的地址,进行传地址的调用,在内存相同的地址区间进行数据的修改。
在实际的应用中,如果需要利用子程序对数组进行处理,函数的调用利用指向数组(一维或多维)的指针作参数,无论是实参还是形参共有下面四种情况:
实参 形参
1 数组名 数组名
2 数组名 指针变量
3 指针变量 数组名
4 指针变量 指针变量
在函数的调用时,实参与形参的结合要注意所传递的地址具体指向什么对象,是数组的首址,还是数组元素的地址,这一点很重要。
6.4.4指针与字符数组
6.5指针的地址分配
ANSI标准建议设置了两个最常用的动态分配内存的函数malloc()和free(),并包含在stdlib.h中,但有些C编译却使用malloc.h包含。
动态内存分配其含义是指:
当定义指针变量时,其变量的取值是随机的,可能指向内存的任一单元。
若指针的指向是不安全的内存地址,在该地址空间上的数据交换就会产生意料不到的效果。
为此,在程序的执行过程中,要保证指针操作的安全性,就要为指针变量分配安全地址。
在程序执行时为指针变量所做的地址分配就称之为动态内存分配。
当无需指针变量操作时,可以将其所分配的内存归还系统,此过程我们称之为内存单元的释放。
malloc()用以向编译系统申请分配内存;free()用以在使用完毕释放掉所占内存。
为指针变量分配的存储空间长度取决于存放字符的多少。
6.6指针数组
6.7指向指针的指针
一个指针变量可以指向整型变量、实型变量、字符类型变量,当然也可以指向指针类型变量。
当这种指针变量用于指向指针类型变量时,我们称之为指向指针的指针变量,
6.8main函数的参数
七:
结构体与共用体
7.1结构体类型变量的定义和引用
7.2结构体数组的定义和引
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 基础 学习 笔记