版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第十章C语言根本知识第一节C语言概述20世纪60年代,贝尔实验室,KenThompson开始开发一个叫做UNIX的操作系统最初的操作系统等系统软件都是用汇编语言编写的,便于直接对硬件及接口进行操作,但依赖于硬件,可读性和可移植性比较差。→高级语言?→集高级语言和低级语言优点于一身?70年,将BCPL语言改造成更适合开发UNIX的B语言73年,DennisM.Ritchie将B语言改造成C语言,把UNIX操作系统的90%以上源代码用C语言改写C语言的设计者Ritchie漫画像1978年,BrianW.Kernighan和DennisM.Richie合著影响深远的名著《TheCProgrammingLanguage》称为标准的C语言版本1983年,美国国家标准化协会对C开展和扩充,制定了新的标准称为ANSICANSIC标准的发布是C语言成熟的标志教科书就是以ANSIC为依据编写的接受美国国家技术勋章一、C语言的版本K&RC标准I/O库长整型数据类型〔longint〕无符号整型〔unsignedint〕复合赋值操作符的形式由“=op〞〔例如“=+〞〕改为“op=〞〔如“+=〞〕以减少歧义ANSIC〔ISOC〕引入的新特征包括:void函数函数返回struct或union类型void*数据类型目前,几乎所有的开发工具都支持ANSIC标准,它是C语言用得最广泛的一个标准版本。一、C语言的版本C99C99引入的新特性包括:内联函数〔inlinefunction〕新的数据类型〔longlongint和complex类型〕变长数组〔variable-lengtharrays〕可变参数宏〔variabicmacro〕以“//〞开头的单行注释ANSIC〔ISOC〕C1X〔X=0-9〕对齐标准多线程支持unicode支持删除gets函数越界检查接口可分析性特征二、C语言的特点
1.C语言兼具高级语言的灵活性和低级语言的高效性2.简洁紧凑、数据结构和运算符丰富3.C是结构式语言4.C语言适用范围广、可移植性好5.C语法限制不太严格、程序设计自由度大6.C语言既有高级语言的特点,又具有汇编语言的特点;既是成功的系统设计语言,又是通用的程序设计语言;三、C语言的编译器和集成开发环境编译程序〔编译器,Compiler〕的功能读入高级语言编写的程序源代码,将其翻译成在逻辑上与之等价的目标程序,即转换成机器代码〔可执行程序〕一种程序设计语言对应一种编译器C语言可执行程序编译器三、C语言的编译器和集成开发环境C语言编译器1.BorlandC++编译器2.Ch解释器3.WatcomC/C++4.GCC5.IntelC/C++编译器6.AMDx86Open64编译器套装7.TinyC三、C语言的编译器和集成开发环境C语言的集成开发环境〔IDE〕1.TurboC2.TurboC++/BorlandC++/C++Builder3.MicrosoftVisualC++4.Code::Blocks5.C-Free6.CodeLite7.Dev-C++C语言与C++的区别:全新的程序程序思维,C语言是面向过程的,而C++是面向对象的。C语言有标准的函数库,它们松散的,只是把功能相同的函数放在一个头文件中;而C++对于大多数的函数都是有集成的很紧密,特别是C语言中没有的C++中的API是对Window系统的大多数API有机的组合,是一个集体。但你也可能单独调用API。特别是C++中的图形处理,它和语言的图形有很大的区别。C语言中的图形处理函数根本上是不能用在C++中的。C语言标准中不包括图形处理。C和C++中都有结构的概念,但是在C语言中结构只有成员变量,而没有成员方法,而在C++中结构中,可以有自己的成员变量和成员函数。C语言可以写很多方面的程序,但是C++可以写得更多更好,C++可以写基于DOSr程序,写DLL,写控件,写系统。C语言对程序的文件的组织是松散的,几乎是全要程序处理;而C++对文件的组织是以工程,各文件分类明确。C++中的IDE很智能,和VB一样,有的功能可能比VB还强。C++对可以自动生成你想要的程序结构,可以节省很多工作时间。有很多可用的工具,如参加MFC中的类,参加变量等等。C++中的附加工具也有很多,可以进行系统的分析,可以查看API;可以查看控件。几点学习建议:
1.根本概念很重要。无论学C,还是学C++,根本概念都是第一位的,也是比较困难的,但只有把握了根本概念才能把握整体脉络,才能居高临下、灵活运用。
2.C是C++的子集,它的根本概念和设计方法相比照较容易理解,初学者可从它入手。
第二节C语言的根本知识#include<stdio.h>intmain(void){ printf("hello,world\n"); return0;}【例10.1】
打印语句Hello,World!
的程序程序说明如下:include<stdio.h>Stdio.h系统头文件,表示可以使用系统提供的函数
intmain(void)开始执行,必须包含且只能有一个main函数,int整型,void空{函数体或代码段的开始标志printf(“hello,world!\n〞);屏幕标准输出格式,\n表示换行,光标移到下行开始位置。}函数体或代码段的结束标志return0;main函数的返回值;表示语句的结束main()一个程序的开始{函数开始的标志inti,j,sum;变量说明,申请存储空间i=2;j=-3;给出两个整数,给变量赋值sum=i+j;作加法,并保存和printf("Thesumofi+jis%d\n",sum);屏幕输出结果}函数结束的标志再看一个例子1.函数是C语言程序的根本单位。main()函数的作用,相当于其它高级语言中的主程序;其它函数的作用,相当于子程序。2.C语言程序总是从main()函数开始执行。一个C语言程序,总是从main()函数开始执行,而不管其在程序中的位置。当主函数执行完毕时,亦即程序执行完毕。习惯上,将主函数main()放在最前头。第二节C语言的根本知识C语言字符集C语言字符集包括52个字母〔C语言区分大小写〕、10个阿拉伯数字、29个特殊字符和4个格式符。29个特殊字符 !+–*/=%'"#{}[]<>().,;:?~^\|_&格式符 空格、水平制表符〔HT〕、垂直制表符〔VT〕、换页符〔FF〕此外的其他字符都只能放在注释语句、字符型常量、字符串型常量中。第二节C语言的根本知识数据类型根本数据类型整型、字符、浮点〔单精度、双精度〕、枚举构造类型数组、结构体〔struct〕和联合〔union〕。指针类型〔*〕空类型〔void〕例10.2输出各种数据类型的最大、最小值#include<stdio.h>#include<stdlib.h>#include<limits.h>#include<float.h>intmain(){printf("%d,%d\n",SHRT_MIN,SHRT_MAX);printf("%u\n",USHRT_MAX);printf("%d,%d\n",INT_MIN,INT_MAX);printf("%u\n",UINT_MAX);printf("%ld,%ld\n",LONG_MIN,LONG_MAX);printf("%lu\n",ULONG_MAX);printf("%d,%d\n",CHAR_MIN,CHAR_MAX);printf("%d,%d\n",SCHAR_MIN,SCHAR_MAX);printf("%d\n",UCHAR_MAX);printf("%.6e,%.6e\n",FLT_MIN,FLT_MAX);printf("%.12e,%.12e\n",DBL_MIN,DBL_MAX);printf("%.15Lf,%.15Lf\n",LDBL_MIN,LDBL_MAX);/*局部编译器不支持*/return0;}教材P245-249给出了各类数据大小及存储第二节C语言的根本知识各种数据类型的存储单精度浮点数用4字节存储,双精度浮点数用8字节存储分为三个局部:符号〔S〕、指数〔E〕和尾数〔M〕
对于整型和字符型数据,以二进制存储于内存单元。第二节C语言的根本知识标识符、变量与常量标识符的命名必须满足以下规那么:1.标识符必须由字母或下划线开头。下划线通常用于连接不同的单词组成较长的标识符,以提高可读性。由于C语言自带的库函数通常以下划线开头,因此标识符命名时不要以下划线开头;2.其它局部可以由字母、下划线或数字组成;3.标识符的有效长度为32个字符;4.标识符不能使用C语言的关键字,所有关键字都必须小写;5.C语言区分字母的大小写;6.标识符命名时尽量能从字面上明确其用途。第二节C语言的根本知识常量整型常量1.十进制常量以非0开始,如:220,-560,45900;2.八进制常量以0开始,如06,0106,05788;3.十六进制常量以0X或0x开始,如0X0D,0XFF,0x4e等。4.可在整型常量后添加一个“l〞或“L〞字母表示其为长整型,如22L,0773L,0Xae4l。5.无符号常量以字母“u〞或“U〞结尾,后缀“ul〞或者“UL〞表示是unsignedlong型。6.对于八进制或十六进制常量,用后缀“L〞表示long类型,后缀“U〞表示unsigned类型。第二节C语言的根本知识常量浮点数常量至少包含小数点或者指数二者之一的常量是浮点数常量,没有后缀时默认为double类型。后缀“f〞或“F〞表示float类型,后缀“l〞或“L〞表示longdouble类型。如:第二节C语言的根本知识常量字符常量字符常量实际上是一个整数,对应的取值可以在ASCII字符集中查找,书写时用单括号内的字符表示,如’c’,‘h’。字符串常量那么将多个字符组成的序列用双引号括起来表示,实际是一个字符数组,也可以是不含任何字符的空字符串“〞。在C语言中,字符串使用一个空字符“\0〞作为字符串的结尾,C语言对字符串的长度没有限制,字符串s的长度可由标准库函数strlen(s)获得,此长度不包括末尾的空字符“\0〞。第二节C语言的根本知识常量枚举常量(enumeration)枚举常量是一个整型常量值的列表,其定义格式为:enum常量名{枚举名列表}如果没有显式说明,枚举类型中第一个枚举名的值为0,第二个为1,依次类推。如果只指定了局部枚举名的值,那么未指定值的枚举名,其取值从最后一个指定值递增。如:enumcolor{RED,ORIENGE,YELLOW,GREEN,CRYN,BLUN,PURPLE}/*RED的值为0,ORIENGE的值为1,依次类推*/enumshape{CIRCLE=2,SQUARE,RECANGUAGLE,TRIANGLE,OVAL}/*CIRCLE的值为2,SQUARE的值为3,依次类推*/第二节C语言的根本知识常量符号常量符号常量即用一个标识符来代表一个常量,其定义使用宏定义命令#define,其格式为#define宏名常数例如:#definePI3.14159265#defineMAX100#defineDEBUG1一旦完成定义后,符号常量的值在作用域内不能改变,也不能再被赋值。第二节C语言的根本知识变量C的变量在使用之前必须先定义其数据类型,未经声明的变量不能使用。例如:Inti,j,k;Doubletemperature,pressure,timestep;在声明的同时可以对变量进行初始化,具体做法是在声明变量之后紧跟一个等号和一个初始化表达式,例如:Inti=max+1;Floatx=1.0;Doubleepsn=1.0e-5;Charc=“y〞;第二节C语言的根本知识运算符和表达式算术运算符算术运算符包括+、-、*、/和%。需要注意的是,整数之间进行除法运算时,会舍掉小数局部。%表示整数之间的取余运算,例如x%y表示x除以y得到的余数,%不能用于float或double类型。算术运算符采用自左至右的结合规那么,*、/、%的优先级高于+、-。如果一个运算符两侧的数据类型不同,系统会自动进行类型转换,转换成同一数据类型后进行运算。如下:运算符和表达式1.字符型数据〔char〕和short型数据转换为整型〔int〕2.单精度类型〔float〕不会自动转换成双精度型〔double〕,这一点与C最初的定义不同。使用float类型主要是为了节约存储空间和执行时间〔双精度计算比较费时〕;3.遇到不同数据类型时,按照数据类型级别的上下,由低向高转换。数据类型级别从低向高依次为:int–>unsigned–>long–>double。数据类型的转换从左至右,当遇到不同类型时才开始转换;4.可以利用强制类型转换将一个变量或表达式转换成所需类型,而该变量或表达式本身的数据类型不变.第二节C语言的根本知识运算符和表达式自增、自减运算符*自增运算符〔++〕的作用是使变量的值加1,而自减运算符〔––〕的作用是使变量的值减1。*自增和自减运算符均为单目运算〔一个操作数〕,具有右结合性。*根据自增、自减运算符作为变量的前缀或者后缀,具体的作用方式不同:i++〔i––〕表示使用i后将i的值加1〔减1〕++i〔––i〕表示将i的值加1〔减1〕后再使用i第二节C语言的根本知识自增、自减运算符#include<stdio.h>main(){inti=10,j=10,m,n;m=(i++)+(i++);n=(++j)+(++j);printf("%d%d%d%d",m,n,i,j);}
注意:自增和自减运算符只能作用于某一个变量,将其作用于表达式是非法的。第二节C语言的根本知识赋值运算符一般形式为:变量=表达式。例如:f=x+y–z;y=sin(a)+exp(x);i=j=k=1;可理解为k=1;j=k;i=j;右结合性如果赋值运算符两边的数据类型不相同,系统将自动进行类型转换,即把赋值号右边的类型换成左边的类型。规定如下:整型变量赋予实型变量时,整数的数值不变,但将增加值为0的小数局部,以浮点形式存放;实型赋予整型时,小数局部无条件舍去;字符型赋予整型时,由于字符型为一个字节,而整型为两个字节,故将字符的ASCII码值放到整型量的低八位字节中,同时将高八位字节设为0;整型赋予字符型时,仅将低八位字节赋予字符型变量。第二节C语言的根本知识第二节C语言的根本知识复合赋值运算符i+=1表示i=i+1C语言里有多种运算符可以实现复合赋值运算〔op=〕,包括:+=–=*=/=%=<<=>>=&=^=|=使用这些符合赋值运算符的时候,通用的表达形式为:exp_aop=exp_b即exp_a=exp_aopexp_b例如:i*=j+1表示i=i*(j+1),而不是i=i*j+1。第二节C语言的根本知识逗号运算符其一般形式为:表达式1,表达式2例如:a=30;b=(a=a+6,a/6);相当于a=30;a+=6;b=a/6;实际应用逗号表达式的时候需要注意:逗号表达式可以嵌套,即逗号表达式可以和另一个表达式通过逗号串联在一起形成新的逗号表达式,因此逗号表达式的一般形式可以表示为:表达式1,表达式2,表达式3,……表达式n整个逗号表达式的取值为表达式n的值。变量说明、函数参数列表中的逗号表示各变量之间的间隔,并不组成逗号表达式。第二节C语言的根本知识C程序的书写每条语句以末尾的分号“;〞表示结束;每行通常写一条语句,也可以写多条语句。如果语句太长,可以拆开换行继续书写,一般不用加续行标志。拆分长行时,应在低优先级操作符处拆分并将该操作符放在新行之首,同时新行适当缩进与上一行的适当位置对齐,这样排版比较整齐,程序易读。C语言中的注释语句以“/*〞开头,以“*/〞结尾,如果注释较长,可以写作多行,包含在“/*〞与“*/〞之间即可;C程序的书写C程序中可以用花括号{}把多个单条语句括起来,组成一个复合语句“{〞和“}〞最好独占一行并且处于同一列,同时与引用它们的语句左对齐;书写“{}〞之内的代码块时,从“{〞开始缩进假设干字符后左对齐;对于{}有嵌套的情况,对同一层次的{}使用缩进对齐。第二节C语言的根本知识代码风格#include<stdio.h>/*对fahr=0,20,...,300
打印华氏温度与摄氏温度对照表*/main(){
int
fahr,celsius;
int
lower,upper,step;
lower=0;/*温度表的下限*/
upper=300;
/*温度表的上限*/
step=20;/*步长*/
fahr
=lower;
while(fahr<=upper){
celsius=5*(fahr-32)/9;
printf("%d\t%d\n",fahr,celsius);
fahr=fahr+step;
}}“代码风格〞的目标是让代码清晰,增强可读性,使代码更容易被他人维护1良好的注释;2整齐的缩进;3适当的空行;4见名知义的变量命名5恰当位置的空格6每行最多只有一条语句一、数据的输入输出〔一〕格式化输入函数scanfscanf(“格式控制字符串列表〞,变量地址列表)scanf(“%d%d%d〞,&i,&j,&k)1˽2˽3i=1;j=2;k=3;scanf(“%d˽%d˽%d〞,&i,&j,&k)1˽˽2˽˽3i=1;j=2;k=3;scanf(“%d,%d,%d〞,&i,&j,&k)1,2,3i=1;j=2;k=3;scanf(“%d,%d,%d〞,&i,&j,&k)1˽2˽3i=1;j、k无法得到正确输入;scanf(“i=%d,j=%d,k=%d〞,&i,&j,&k)i=1,j=2,k=3i=1;j=2;k=3;第三节输入输出及流程控制scanf()函数,格式字符串更为一般的形式为:%[*][数据宽度][修饰符]格式字符“*〞表示该输入项读入后不赋予变量地址列表中对应位置的变量,即跳过该输入值。例如scanf("%d%*d%d",&i,&j);当输入为:123时,把1赋予i,3赋予j,而2被跳过。数据宽度为一正整数,用来指定输入数据所占列宽。如scanf(“%d%2d%3d〞,&i,&j,&k);当输入123456时,i=1,j=23,k=456修饰符包括l和h,其中l可以用来修饰d、o、x、f或e,表示输入longint或longdouble类型;h用来修饰d、o、x,表示输入shortint类型。具体写法是:%ld,%lo,%lx,%lf,%le和%hd,%ho,%hx第三节输入输出及流程控制输入数据时不能规定小数点后面的位数,即数据的精度【错误】scanf(“%8.3f〞,&x);【正确】scanf(“%f〞,&x);在用“%c〞输入字符时,所有的键盘输入包括空格和转义字符都会作为有效字符输入。例如对于如下语句scanf(“%c%c〞,&ch1,&ch2);当输入x˽y时,ch1=x,而ch2=˽对于字符串数组或字符串指针变量,由于数组名和指针变量名本身就是地址,因此使用scanf()函数时,不需要在它们前面加上“&〞操作符。%:格式控制符&:地址运算符,变量地址列表符格式字符见表10-6第三节输入输出及流程控制〔二〕格式化输出函数printfprintf函数的一般形式为:printf(“格式控制字符串列表〞,变量列表);
printf(“%d%d〞,i,j); 当i=1、j=2时输出:12printf(“i=%d,j=%d\n〞,i,j); 当i=1、j=2时输出:i=1,j=2并换行
第三节输入输出及流程控制〔二〕格式化输出函数printfprintf函数格式字符串的一般形式为:%[标志][输出最小宽度m][精度.n][长度]类型
inti=1,j=-2;printf("%3d%3d\n",i,j); 输出:˽˽1˽-2printf("%-3d%-3d\n",i,j); 输出:1˽˽-2˽printf("%+3d%+3d\n",i,j); 输出:˽+1˽-2printf("%03d%03d\n",i,j); 输出:001˽-02printf("%0+3d%0+3d\n",i,j); 输出:+01-02doublex=0.123,y=-0.456;printf("%f˽%f\n",x,y); 输出:0.123000˽-0.456000printf("%+f˽%+f\n",x,y); 输出:+0.123000˽-0.456000printf("˽%f˽%f\n",x,y); 输出:˽0.123000˽-0.456000printf("%8.3f˽%8.3f\n",x,y); 输出:˽˽˽0.123˽˽˽-0.456printf("%08.3f˽%08.3f\n",x,y); 输出:0000.123˽-000.456printf("%-08.3f˽%08.3f\n",x,y); 输出:0.123˽-000.456第三节输入输出及流程控制一、逻辑运算与条件语句〔一〕关系运算符与关系运算表达式关系运算符>>=<<===!=表达式1关系运算符表达式2x>y+za<=11/5‘A’+3>‘C’〔字符变量以它对应的ASCII码参与运算〕j==i+1p+q!=m–nC语言没有逻辑型数据,“真〞和“假〞分别用整数“1〞和“0〞表示第三节输入输出及流程控制二、逻辑运算与条件语句〔一〕关系运算符与关系运算表达式i=1;j=2;k=3;printf(“%d〞,i>0);i>0的值为真,故输出为1
printf(“%d〞,i==j<k);j<k的值为真,等于i的值,故i==j<k的值为真,输出结果为1
printf(“%d〞,n=k>j>i);关系运算符的优先级高于赋值预算,因此首先根据关系运算的左结合性执行k>j,其值为1,再执行1>i,其值为0,最后执行赋值操作,n的值为0第三节输入输出及流程控制二、逻辑运算与条件语句〔二〕逻辑运算符与逻辑表达式逻辑运算符&&||!5>3||5<3 相当于(5>3)||(5<3)5>3成立,结果为真,5<3不成立,结果为假,但整个表达式的值为1!0==1>0&&2!=5–1相当于((!0)==(1>0))&&(2!=(5–1));!0的结果为1,1>0的结果为1,所以(!0)==(1>0)的结果为真;2!=(5–1)的结果为真,所以整个表达式的结果为真,即数值1。第三节输入输出及流程控制二、逻辑运算与条件语句〔二〕逻辑运算符与逻辑表达式C语言在判断一个表达式的值为真或假时,所有非0的数值都判断为真,即数值1;仅0值被判断为假,即数值0。例如:a=10时,由于a非0,所以!a的值为0;a=10、b=20时,a&&!(b–20)的值为1。因为a为真,且!(b–20)也为真;9–!0!=8&&5+3||0==!3的值为1。对于该表达式,先计算!0,其值为1,9–!0的值为8,所以9–!0!=8的值为假〔0〕;5+3的结果为8非0为真,所以9–!0!=8&&5+3的值仍为假〔0〕;0==!3的结果为真,所以整个表达式的最终结果为真。第三节输入输出及流程控制二、逻辑运算与条件语句〔三〕if语句if(表达式)语句if(表达式)语句1else语句2if(表达式1) 语句1;else 语句2;或者if(表达式1){……}else{ ……}第三节输入输出及流程控制二、逻辑运算与条件语句〔四〕条件运算符和条件表达式表达式1?表达式2:表达式3min=a<b?a:b表示a<b时min=a,否那么min=b,也就是说,把a和b两者的较小值赋给min。如果用if语句改写,可以写作:if(a<b) min=a;else min=b;第三节输入输出及流程控制三、循环语句〔一〕for语句for(表达式1;表达式2;表达式3)语句for(i=0;i<100;i++)语句该语句先给循环变量i赋初值1,然后判断i是否小于100。假设是那么执行语句,之后i值加1。假设i>=100,那么结束。for(i=100;i>=0;i-=2)语句先给循环变量i赋初值100,然后判断i是否大于0。假设是那么执行循环体语句,之后i值减2。假设i<0,那么结束。for(i=0;;i+=2)语句先给循环变量i赋初值0,执行语句后i值加2,反复执行循环体语句。for(;;)语句反复执行循环体语句第三节输入输出及流程控制#include<stdio.h>main(){inti,sum;
sum=0;for(i=1;i<=100;i++)sum+=i;
printf("1+2+...+100=%d\n",sum);}
#include<stdio.h>main(){inti,m,n;scanf("%d",&n);for(m=1,i=1;i<=n/5;i++,m++)
printf("%d\n",m*5);}三、循环语句〔二〕while语句while(表达式)语句#include<stdio.h>main(){inti,sum;i=sum=0;while(i<=100){sum+=i;i++;}printf("1+2+...+100=%d\n",sum);}第三节输入输出及流程控制三、循环语句〔三〕循环语句嵌套#include<stdio.h>main(){inti,j;for(i=1;i<=9;i++){for(j=1;j<=i;j++)printf("%d*%d=%d",i,j,i*j);printf("\n");}}第三节输入输出及流程控制三、循环语句〔四〕goto、break与continue语句goto语句goto语句用来实现无条件跳转,从一条语句转移到另一条语句。其格式为goto语句标签;其中语句标签不能是整数,而必须服从变量命名规那么,由字母、数字和下划线组成,后面加上冒号。例如:gotoquit;第三节输入输出及流程控制三、循环语句〔四〕goto、break与continue语句break语句跳出本次循环#include<stdio.h>main(){inti,j;for(i=1;i<=9;i++){for(j=1;j<=9;j++){printf("%d*%d=%d",i,j,i*j);if(j>=i)break;}printf("\n");}}第三节输入输出及流程控制三、循环语句〔四〕goto、break与continue语句continue语句结束本次循环#include<stdio.h>main(){inti,j;for(i=1;i<=9;i++){for(j=1;j<=9;j++){if(j>=i)continue;printf("%d*%d=%d",i,j,i*j);
}printf("\n");}}第三节输入输出及流程控制一、指针指针存放的是变量的地址物理地址:0x00000000到0xFFFFFFFF逻辑地址:程序中用到的相关变量、数据或者代码相对于这个起始地址的位置〔由编译器分配〕变量的逻辑内存地址可以用指针这种特殊的变量来存储直接存取:按变量名〔即变量的地址〕直接存取变量值间接存取:用指针这种特殊的变量进行内存存取第四节指针与数组00000001inti0x0022FEDC0x0022FF08int*p二、指针变量的一般形式
数据类型*标识符标识符代表指针变量的名字,必须按照符合C语言对标识符命名的规定。一个指针变量只能指向同类型的变量,数据类型定义了指针变量的类型及其所指向的变量的类型。第四节指针与数组三、指针变量与其所指向的变量之间的关系inti,*p;声明了一个整型变量i和一个指向整型变量的指针变量p。p只能指向整型变量,*p代表p所指向的变量。p=&i; 使用取地址运算符“&〞可以得到变量i的地址,并将其赋给指针变量p,也就是将p指向i,通过存放在p中的i的地址可以对i进行操作。由于*p表示p所指向的内容,因此*p和i可以认为是等价的。第四节指针与数组指针也可以由const声明为常量,区别:intconst*p;
声明了一个指向整型常量的指针p。此时可以修改指针的值,但不能修改它所指向的整型常量的值;int*constp; 声明了一个指向整型变量的指针常量p。此时不可以修改指针的值,但可以修改它所指向的整型变量的值;intconst*constp; 声明了一个指向整型常量的指针常量p。此时不可以修改指针的值,也不可以修改它所指向的整型变量的值。第四节指针与数组第四节指针与数组#include<stdio.h>#include<stdlib.h>intmain(){floatconstpi=3.14;constfloate=2.72;floatconst*p;float*constq=&e;floatconst*constr=πp=π*p=3.14159265;/*wrong*/printf("%p,%f\n",p,*p);q=&e;/*wrong*/*q=2.71828;printf("%p,%f\n",q,*q);r=&e;/*wrong*/*r=3.14159265;/*wrong*/printf("%p,%f\n",r,*r);return0;}四、指针运算符*和取地址运算符&*表示其后的标识符为指针变量当指针指向某一个变量时,*运算表示通过指针变量存储的地址间接访问指针指向的变量,此时*称作间接寻址或间接引用运算符。&那么表示变量的地址&运算符只能应用于内存中的对象,如变量和数组元素,但不能应用于表达式和常量。*和&运算的优先级相同,均具有从右至左的结合性。 *&i; 按照从右至左的结合性,先计算&i,得到i变量的地址。*运算表示取出后面变量地址中的内容,因此*&i等价于i变量。 &*p; 按照从右至左的结合性,相当于取*p的地址,而*p与i等价,因此&*p相当于&i。 (*p)++ *p与i等价,相当于i++。第四节指针与数组五、指针变量的赋值与初始化(1)把一个变量的地址赋予指向与其数据类型相同的指针变量。floatx,*p;声明一个float类型的变量x和一个指向float类型的指针变量p;p=&x; 把float型变量x的地址赋予float型指针变量p。(2)把一个指针变量的值赋予指向相同类型变量的另一个指针变量。chars; 声明一个字符型变量;char*p1,*p2; 定义两个指向字符型变量的指针;p1=&s; 把char型变量s的地址赋予char型指针变量p;p2=p1; 把p1的值〔地址〕赋予p2。第四节指针与数组五、指针变量的赋值与初始化(3)声明指针变量的同时初始化。
doubley,*p=&y;
声明了一个double类型的变量y和一个指向double类型的指针变量p,并将p指向一,也就是把y的地址赋给p。 doubley,*p;
*p=1.0;本例的错误在于,p未经初始化,所以不知道它指向哪里,无法赋值。第四节指针与数组六、NULL指针对于外部或静态指针变量,如果声明的同时没有初始化,那么指针变量被初始化0。此时指针不指向任何有效数据,有时也称指针为空指针〔NULL指针〕。除了初始化以外,要使指针变量为NULL,可以给它赋一个0值。与0值进行比较也可以测试指针变量是否为NULL。对指针变量不赋值不同于赋0值。如果指针变量未赋值,说明它尚未指向任何变量或内存地址。第四节指针与数组七、指向指针的指针 定义一个变量,存储某个指针变量的地址,这就是所谓指向指针的指针,其声明方式如下: 数据类型名**变量名其中,**表示后面的变量是一个指向指针的指针,它本身与其指向的指针具有同一数据类型。inti;int*p=&i;声明一个指向整型变量的指针变量p,并指向整型变量i;
int**pp=&p;
声明一个指向整型指针的整型指针pp,并指向整型指针p,也就是存放了p的地址。此时,*pp代表p变量的值,也就是i的地址,**pp相当于*(*pp),也就是间接访问i的地址并取得i的值。第四节指针与数组例10-15用指针变量查看内存分配#include<stdio.h>intmain(){inti=1,j=-2,k=3;floatx=0.123,y=-0.456;chars[26]="abcdefghijklmnopqrstuvwxyz";unsignedchar*p;p=(unsignedchar*)(&i);
printf("%p,%x\n",p,*p);printf("%p,%p,%p\n",&i,&j,&k);printf("%p,%p\n",&x,&y);
for(i=0;i<26;i++)printf("%p,%x\n",&s[i],s[i]);return0;}第四节指针与数组八、数组类型数组名[第n维长度][第n-1维长度]...[第1维长度]; 类型是指数组元素的数据类型,包括整数型、实数型、字符型、指针型,或者结构体和联合体等。数组名需要按照标识符的命名规那么来命名,成员的引用由“[]〞完成。每一维的长度,可以是常数,也可以是常量表达式。inta[10]; 声明了一个具有10个整型数元素的数组a;unsignedlongb[20]; 声明了一个具有20个长整型元素的数组b;floatx[10][10]; 声明了一个10×10的二维单精度实数型数组x;doubley[5][5][5]; 声明了一个5×5×5的三维双精度实数型数组y;chars[10]; 声明了一个能容纳5个字符的字符数组s;说明如下:第四节指针与数组八、数组数组以0作为第一个元素的下标。例如,当定义一个inta[10]的整型数组时,说明该数组共有10个整型变量元素:a[0]~a[9];数组必须先定义,后使用。不能像Fortran一次引用整个数组,必须逐个引用数组元素。引用时,下标可以是整型变量或者整型表达式。 【错误】【正确】 inta[10]; inta[10],i; a=5; for(i=0;i<10;i++)a[i]=5;C语言对数组不作越界检查;多维数组行主存储,即最右边的下标变化最快;C语言不允许使用动态数组,因此常量表达式中仅能使用常量和符号常量,不能包含变量。第四节指针与数组九、数组元素的初始化 初始化赋值的一般形式为: static类型说明符数组名[常量表达式]={值,值……值}; 如:staticfloatx[5]={0.1,0.2,0.3,0.4,0.5};几点规定:可被初始化但未赋初值的数组,其初值默认为0;当{}中值的个数少于数组的元素个数时,只按顺序给前面局部元素赋值。例如:staticinta[10]={0,1,2,3,4};表示只给a[0]~a[4]5个元素赋值,而后5个元素自动赋0值。不能对数组进行整体赋值。例如给10个元素全部赋同样的值,只能写为:staticinta[10]={1,1,1,1,1,1,1,1,1,1};而不能写为:staticinta[10]=1;第四节指针与数组九、数组元素的初始化对于多维数组,可以按照行主存储顺序给数组元素赋值,例如:staticinta[2][2]={0,1,2,3};表示a[0][0]=0,a[0][1]=1,a[1][0]=2,a[1][1]=3。也可以分行给多维数组赋初值,如: staticinta[2][3]={{1,2,3},{4,5,6}};还可以只对局部元素赋值,如: staticinta[3][3]={{1},{0,2},{0,0,3}};如果对数组的全部元素赋值,那么在一维数组的说明中可以不给出数组元素的个数。例如:staticinta[5]={1,2,3,4,5};可写为:staticinta[]={1,2,3,4,5};对于多维数组,第一维的长度可以不指定,但后面各维的长度不能省。如: staticinta[][2]={1,2,3,4};第四节指针与数组例10-16打印杨辉三角形#include<stdio.h>#defineN5intmain(){inti,j,a[N][N];for(i=0;i<N;i++){a[i][0]=1;a[i][i]=1;}for(i=2;i<N;i++)
for(j=1;j<i;j++)a[i][j]=a[i-1][j-1]+a[i-1][j];for(i=0;i<N;i++){for(j=0;j<=i;j++)printf("%4d",a[i][j]);
printf("\n");}return0;}
第四节指针与数组第五节函数经典方式:函数类型函数名〔形式参数表〕{ 形式参数类型声明 其它变量声明 语句}例如:voidswap(a,b)
; /*声明一个无返回值的函数swap*/{ inta,b; /*说明形式参数的类型*/ …}floatdistance(x,y);/*声明一个返回单精度实数的函数distance*/{ floatx,y; /*说明形式参数的类型*/ …}第五节函数ANSI规定方式函数类型函数名〔数据类型
形式参数,数据类型
形式参数,...〕{ 其它变量声明 语句}例如:voidswap(inta,intb)
; /*声明一个无返回值的函数swap*/floatdistance(floatx,floaty);/*声明一个返回单精度实数的函数distance*/char*result(charstring); /*声明一个返回指向字符串的函数result*/voidsub(void); /*声明一个无返回值和形参的函数sub*/第五节函数函数声明的本卷须知:函数类型实际是该函数返回值的数据类型,可以是以前介绍的各种数据类型,也可以是对应于无返回值的无值型〔void〕,也可以是指针。函数名是由用户定义的标识符,它是一个地址常量,指向函数声明在内存中实际分配地址段的首地址;函数名后的括号内是形式参数列表。在进行函数调用时,主调函数将赋予这些形式参数实际的值。由于形参是变量,必须进行类型说明。当采用经典的函数声明方式时,()中给出形式参数列表,在函数体内对形式参数进行类型说明;而当采用ANSI方式时,()中可以直接给出形式参数列表及其类型说明。如果某函数无需形式参数,()内可以为空或者写void,但不能省略。{}中的内容称为函数体,一般包括声明局部和语句局部。当函数有返回值时,至少应有1个return语句作为函数的返回值返回给主调函数。第五节函数函数的调用函数调用的一般形式为: 函数名(实际参数表) 其中,实际参数表中的参数可以是常数、变量或其它构造类型数据及表达式。各实参之间用逗号分隔,实际参数与函数说明中的形式参数必须在位置上一一对应。对于有值函数 dis=distance(x,y); /*函数作为表达式中的1项*/ d=min(a,max(b,c)); /*max函数作为min函数的1个实参*/对于无值函数printf(“%f%f\n〞,x,y);swap(a,b);第五节函数函数的调用主调函数中应对被调函数的返回值类型做出说明,其一般形式为: 函数类型函数名();
函数的说明是对已定义的函数的返回值进行类型说明,只包括函数类型、函数名和一个空括号,不需要包括形参和函数体。#include<stdio.h>intmain(){floatdistanc();/*distance函数说明*/……}floatdistance(floatx,floaty){……}
第五节函数函数的调用C语言规定,以下几种情况可以不在调用函数前对被调函数做出类型说明:(1)函数的返回值为整型或字符型。(2)被调函数出现在主调函数之前。(3)在文件的开头,所有函数定义之前说明了函数的类型,那么在各个主调函数中不必再对所调用的函数做出类型声明。#include<stdio.h>floatdistanc();/*distance函数说明*/intmain(){……}floatdistance(floatx,floaty){……}第五节函数标准库函数 库函数是编译器开发公司为了方便用户使用而将一些常用的功能以函数的形式实现,放在库〔lib〕里供用户直接调用,不同编译器的库函数一般都是有差异的。为了对各种操作系统上的C程序提供可移植性保证,ANSIC定义了一个标准库。C编译器自身的函数库一般都兼容C标准函数库。如:assert.h 定义了assert宏供除错使用ctype.h 判
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026广东广州市越秀区登峰街道办事处招聘辅助人员1人考试参考试题及答案解析
- 北京市顺义区城区社区卫生服务中心招聘编外6人考试备考试题及答案解析
- 2026黄河勘测规划设计研究院有限公司招聘高校毕业生(进站博士后)补充笔试备考试题及答案解析
- 2026中联重科招聘111人笔试模拟试题及答案解析
- 沧州渤海新区中学数字化地理教室项目招标文件
- 2026广西防城港东兴市教育系统公开招聘第二批次中小学临聘教师16人笔试备考试题及答案解析
- 2025年正德职业技术学院单招综合素质考试试题及答案解析
- 2026内蒙古通辽市科左后旗招聘社区残疾人专职委员10人考试备考试题及答案解析
- 2026重庆市长寿区选拔社区工作者后备库人选200人笔试模拟试题及答案解析
- 2026云南省阜外心血管病医院招聘5人考试备考试题及答案解析
- 交通运输安全管理责任绩效考核表
- 《中国养老金精算报告2025-2050》原文
- 宫颈癌根治性放疗指南2026
- 2026年春节后复工复产安全培训试题(附答案)
- 塞来昔布课件
- 柱间支撑按拉杆还是压杆计算的浅析
- 温暖医患关系故事集
- 2025年江苏省省直及部分省辖市事业单位招聘考试真题试卷 公共基础知识带答案详解(完整版)
- 规范项目管理执行的方案
- 施工安全防护用品方案
- 电工三级(高级工)复习题库及答案
评论
0/150
提交评论