




已阅读5页,还剩201页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C程序设计 计算机基础教研室 第8章 指针 重庆工学院计算机学院 第8章指针 C程序设计中使用指针可以 使程序简洁 紧凑 高效有效地表示复杂的数据结构动态分配内存得到多于一个的函数返回值 指针是一种特殊的数据类型 指针概念是C语言中较难理解和较难掌握的概念 8 1指针与指针变量的概念 要明白什么是指针 必须弄清楚数据在内存中是如何存储的 又是如何读取的 内存区的每一个字节有一个编号 这就是 地址 如果在程序中定义了一个变量 在对程序进行编译时 系统就会给这个变量分配内存单元 变量与地址 程序中 inti floatk 内存中每个字节有一个编号 地址 i k 编译或函数调用时为其分配内存单元 变量是对程序中数据存储空间的抽象 指针与指针变量指针 一个变量的地址指针变量 专门存放变量地址的变量在 语言中 指针是一种特殊的变量 它是存放地址的 2000 指针 指针变量 变量的内容 变量的地址 变量的直接访问与间接访问直接访问 按变量地址存取变量值间接访问 通过存放变量地址的变量去访问变量 例i 3 直接访问 3 例 i pointer 20 间接访问 20 两种访问方式 相当于某人甲 系统 要找某人乙 变量 来类比 有两种方法 1 甲知道乙在何处 直接去找就是 即直接访问 2 甲不知道乙在哪 但丙 指针变量 知道 此时甲可以这么做 先找丙 从丙处获得乙的去向 然后再找乙 即间接访问 指针变量与其所指向的变量之间的关系 两种访问方式的特点 8 2指针变量的定义和引用 指针变量的定义一般形式 存储类型 数据类型 指针名 合法标识符 指针变量本身的存储类型 指针的目标变量的数据类型 表示定义指针变量不是 运算符 例int p1 p2 float q staticchar name 注意 1 int p1 p2 与int p1 p2 2 指针变量名是p1 p2 不是 p1 p23 指针变量只能指向定义时所规定类型的变量4 指针变量定义后 变量值不确定 应用前必须先赋值 指针变量的初始化一般形式 存储类型 数据类型 指针名 初始地址值 赋给指针变量 不是赋给目标变量 例inti int p 变量必须已说明过类型应一致 例inti int p 用已初始化指针变量作初值 例main inti staticint p 不能用auto变量的地址去初始化static型指针 例main inti 10 int p p i printf d p 危险 例main inti 10 k int p p 指针变量必须先赋值 再使用 零指针与空类型指针零指针 空指针 定义 指针变量值为零表示 int p 0 p指向地址为0的单元 系统保证该单元不作它用表示指针变量值没有意义 defineNULL0int p NULL p NULL与未对p赋值不同用途 避免指针变量的非法引用在程序中常作为状态比较 例int p while p NULL void 类型指针表示 void p 使用时要进行强制类型转换 例char p1 void p2 p1 char p2 p2 void p1 表示不指定p是指向哪一种类型数据的指针变量 指针变量是一种特殊的变量 变量中存放的不是某种数据类型的数据 而是另一个变量或常量的地址 指针变量的操作主要包括 1 取地址运算 则 ptr 表示指针ptr x 表示变量x 具体描述见下页 指针变量的引用与操作 与 运算符含义 含义 取变量的地址单目运算符优先级 2结合性 自右向左 含义 取指针所指向变量的内容单目运算符优先级 2结合性 自右向左 两者关系 互为逆运算理解 i pointer 指针变量 它的内容是地址量 i pointer 指针的目标变量 它的内容是数据 i pointer 指针变量占用内存的地址 i pointer i i pointer i i pointer i i pointer i i pointer i i pointer i 1 赋值运算 例如 intx p1 p2 p1 p2指针赋值 2 指针变量运算 指针变量 只有加或减的操作 指针由当前所指向的位置向前或向后移动n个数据元素的位置 移动后的实际地址为 p n sizeof 数据类型 3 指针的关系运算指向同种数据类型的指针可作关系运算 表示它们所存放的地址之间的关系 可使用的运算符 8 3指针和地址运算 例指针例题 main inta int pa 运行结果 a 10 pa 10 a f86 hex pa f86 hex pa f88 hex 指针赋值方法 和指针相互赋值 例输入两个数 并使其从大到小输出 main int p1 p2 p a b scanf d d 运行结果 a 5 b 9max 9 min 5 5 2006 9 2008 2006 2008 2006 指针变量作为函数参数 值传递特点 不共享内存 swap intx inty inttemp temp x x y y temp main inta b scanf d d 例将数从大到小输出 5 9 5 5 9 COPY 值传递 运行结果 5 9 swap int p1 int p2 intp p p1 p1 p2 p2 p main inta b int pointer 1 pointer 2 scanf d d 5 9 2000 2002 5 9 COPY 5 例将数从大到小输出 地址传递 共享内存 双向 传递 地址传递 运行结果 9 5 swap int p1 int p2 int p p p1 p1 p2 p2 p main inta b int pointer 1 pointer 2 scanf d d 运行结果 9 9 编译警告 结果不对 intx int p 例将数从大到小输出 5 9 2000 2002 9 9 COPY 假设2000 指针变量在使用前必须赋值 数组在内存中 每一个数组元素都有一个固定的地址 这个地址可以用指针变量来进行操作 数组中指针的概念 数组的指针 数组在内存中的起始地址 数组元素的指针 数组元素在内存中的起始地址指向数组的指针变量的定义intarray 10 pointer array intarray 10 pointer 数组名代表数组在内存中的起始地址 即下标为0的元素的地址 所以可用数组名给指针变量赋值数组元素的引用既可用下标法 也可用指针法 使用下标法 直观 而使用指针法 能使目标程序占用内存少 运行速度快 8 4指针与数组 指向数组元素的指针变量 例intarray 10 int p p 数组名是表示数组首地址的地址常量 指针在数组及其它的运算指针变量的赋值运算p 指针变量p2值 p1 不能把一个整数 p 也不能把p的值 整型变量 如inti p p 1000 i p 指针变量与其指向的变量具有相同数据类型 指针的算术运算 p i p i d i为整型数 d为p指向的变量所占字节数 p p p i p i p i p i等若p1与p2指向同一数组 p1 p2 两指针间元素个数 p1 p2 dp1 p2无意义 例p指向float数 则p 1 p 1 4 例p指向int型数组 且p 则p 1指向a 1 例inta 10 int p 例inta 10 int p1 1 指针变量的关系运算若p1和p2指向同一数组 则p1p2表示p1指的元素在后p1 p2表示p1与p2指向同一元素若p1与p2不指向同一数组 比较无意义p NULL或p NULL 数组元素表示方法 变址运算符a i a i a i p i p i a i 例数组元素的引用方法 main inta 5 pa i for i 0 i 5 i a i i 1 pa a for i 0 i 5 i printf pa d d n i pa i for i 0 i 5 i printf a d d n i a i for i 0 i 5 i printf pa d d n i pa i for i 0 i 5 i printf a d d n i a i 例inta 1 2 3 4 5 6 7 8 9 10 p a i 数组元素地址的正确表示 A a 1 B a C p D p i 数组名是地址常量p p a a a 1 a 2 例voidmain inta 5 8 7 6 2 7 3 inty p 输出 56 例注意指针变量的运算 6 main inti p a 7 p a for i 0 i 7 i scanf d p printf n for i 0 i 7 i p printf d p 例注意指针的当前值 p a 指针变量可以指到数组后的内存单元 数组名作函数参数数组名作函数参数 是地址传递数组名作函数参数 实参与形参的对应关系 例将数组a中的n个整数按相反顺序存放 实参与形参均用数组 voidinv intx intn intt i j m n 1 2 for i 0 i m i j n 1 i t x i x i x j x j t main inti a 10 3 7 9 11 0 6 7 5 4 2 inv a 10 printf Thearrayhasbeenreverted n for i 0 i 10 i printf d a i printf n m 4 例将数组a中的n个整数按相反顺序存放 voidinv int x intn intt p i j m n 1 2 i x j x n 1 p x m for i p i j t i i j j t main inti a 10 3 7 9 11 0 6 7 5 4 2 inv a 10 printf Thearrayhasbeenreverted n for i 0 i 10 i printf d a i printf n 实参用数组 形参用指针变量 例将数组a中的n个整数按相反顺序存放 voidinv int x intn intt i j p m n 1 2 i x j x n 1 p x m for i p i j t i i j j t main inti a 10 p a for i 0 i 10 i p scanf d p p a inv p 10 printf Thearrayhasbeenreverted n for p a p a 10 p printf d p 实参与形参均用指针变量 例将数组a中的n个整数按相反顺序存放 voidinv intx intn intt i j m n 1 2 for i 0 i m i j n 1 i t x i x i x j x j t main inti a 10 p a for i 0 i 10 i p scanf d p p a inv p 10 printf Thearrayhasbeenreverted n for p arr p arr 10 p printf d p 实参用指针变量 形参用数组 一级指针变量与一维数组的关系int p与intq 10 数组名是指针 地址 常量p q p i是q i 的地址数组元素的表示方法 下标法和指针法 即若p q 则p i q i p i q i 形参数组实质上是指针变量 即intq int q在定义指针变量 不是形参 时 不能把int p写成intp 系统只给p分配能保存一个指针值的内存区 一般2字节 而给q分配2 10字节的内存区 指针与二维数组二维数组的地址 对于一维数组 1 数组名array表示数组的首地址即 array 0 的地址 2 数组名array是地址常量 3 array i是元素array i 的地址 4 array i array i 对于二维数组 1 a是数组名 包含三个元素a 0 a 1 a 2 2 每个元素a i 又是一个一维数组 包含4个元素 inta 3 4 基类型 行指针与列指针 对二维数组inta 3 4 有a 二维数组的首地址 即第0行的首地址a i 第i行的首地址a i a i 第i行第0列的元素地址a i j a i j 第i行第j列的元素地址 a i j a i j a i j a i a i a i a i a i 0 值相等 含义不同a i a i 表示第i行首地址 指向行a i a i a i 0 表示第i行第0列元素地址 指向列 二维数组元素表示形式 1 a 1 2 2 a 1 2 3 a 1 2 4 a 0 0 1 4 2 地址表示 1 a 1 2 a 1 0 3 a 1 4 a 1 5 int a 1 地址表示 1 a 1 2 2 a 1 2 3 a 1 2 4 a 0 0 1 4 2 二维数组的指针变量指向二维数组元素的指针变量 例指向二维数组元素的指针变量 main staticinta 3 4 1 3 5 7 9 11 13 15 17 19 21 23 int p for p a 0 p a 0 12 p if p a 0 4 0 printf n printf 4d p p a p 指向一维数组的指针变量 指向m个元素构成的一维数组指针变量 定义形式 数据类型 指针名 一维数组维数 例int p 4 不能少int p 4 与int p 4 不同 p的值是一维数组的首地址 p是行指针 可让p指向二维数组某一行如inta 3 4 p 4 a 一维数组指针变量维数和二维数组列数必须相同 例一维数组指针变量举例 main staticinta 3 4 1 3 5 7 9 11 13 15 17 19 21 23 inti j p 4 for p a i 0 i 3 i p for j 0 j 4 j printf d p j printf n p a 0 p a p p 0 j 例二维数组与指针运算 main inta 3 4 1 2 3 4 3 4 5 6 5 6 7 8 inti int p 4 a q a 0 for i 0 i 3 i if i 0 p i i 2 q 1 elsep q for i 0 i 3 i printf d a i i printf d d n int p q 运行结果 2 4 7 5 3 2 二维数组的指针作函数参数用指向变量的指针变量用指向一维数组的指针变量用二维数组名 例3个学生各学4门课 计算总平均分 并输出第n个学生成绩 main voidaverage float p intn voidsearch float p 4 intn floatscore 3 4 65 67 79 60 80 87 90 81 90 99 100 98 average score 12 search score 2 voidaverage float p intn float p end sum 0 aver p end p n 1 for p p end p sum sum p aver sum n printf average 5 2f n aver voidsearch float p 4 intn inti printf No d n n for i 0 i 4 i printf 5 2f p n i 列指针 行指针 函数说明 floatp 4 p n i 例 3个学生各学4门课 计算总平均分 并查找一门以上课不及格学生 输出其各门课成绩 p j i 二维数组与一维数组指针变量的关系如inta 5 10 与int p 10 二维数组名是一个指向有10个元素的一维数组的指针常量p a i使p指向二维数组的第i行 p i j a i j 二维数组形参实际上是一维数组指针变量 即intx 10 int x 10 变量定义 不是形参 时两者不等价系统只给p分配能保存一个指针值的内存区 一般2字节 而给a分配2 5 10字节的内存区 8 5指针与字符串字符串表示形式用字符数组实现 例main charstring IloveChina printf s n string printf s n string 7 用字符指针实现 例main char string IloveChina printf s n string string 7 while string putchar string 0 string 字符指针初始化 把字符串首地址赋给string char string string IloveChina string 0 字符串指针作函数参数 例用函数调用实现字符串复制 1 用字符数组作参数 2 用字符指针变量作参数 voidcopy string charfrom charto inti 0 while from i 0 to i from i i to i 0 main chara Iamateacher charb Youareastudent printf string a s nstring b s n a b copy string a b printf nstring a s nstring b s n a b voidcopy string char from char to for from 0 from to to from to 0 main char a Iamateacher char b Youareastudent printf string a s nstring b s n a b copy string a b printf nstring a s nstring b s n a b 字符指针变量与字符数组char cp 与charstr 20 str由若干元素组成 每个元素放一个字符 而cp中存放字符串首地址charstr 20 str IloveChina char cp cp IloveChina str是地址常量 cp是地址变量cp接受键入字符串时 必须先开辟存储空间 例charstr 10 scanf s str 而char cp scanf s cp 改为 char cp str 10 cp str scanf s cp 字符串与数组关系字符串用一维字符数组存放字符数组具有一维数组的所有特点数组名是指向数组首地址的地址常量数组元素的引用方法可用指针法和下标法数组名作函数参数是地址传递等区别存储格式 字符串结束标志赋值方式与初始化输入输出方式 s c charstr Hello charstr Hello charstr H e l l o char cp Hello inta 1 2 3 4 5 int p 1 2 3 4 5 charstr 10 cp inta 10 p str Hello cp Hello a 1 2 3 4 5 p 1 2 3 4 5 scanf s str printf s str gets str puts str 8 6指针数组和多级指针如果希望使用多个指针变量来操作 可定义指针数组指针数组定义 数组中的元素为指针变量定义形式 存储类型 数据类型 数组名 数组长度说明 例int p 4 指针所指向变量的数据类型 指针本身的存储类型 区分int p 4 与int p 4 指针数组赋值与初始化 指针数组赋值与初始化 charname 5 9 gain much stronger point bye char name 5 gain much stronger point bye 二维数组与指针数组区别 二维数组存储空间固定字符指针数组相当于可变列长的二维数组分配内存单元 数组维数 2 各字符串长度 指针数组元素的作用相当于二维数组的行名但指针数组中元素是指针变量二维数组的行名是地址常量 main intb 2 3 pb 2 inti j for i 0 i 2 i for j 0 j 3 j b i j i 1 j 1 pb 0 b 0 pb 1 b 1 for i 0 i 2 i for j 0 j 3 j pb i printf b d d 2d n i j pb i 例用指针数组处理二维数组 例对字符串排序 简单选择排序 main voidsort char name intn print char name intn char name Followme BASIC GreatWall FORTRAN Computer intn 5 sort name n print name n voidsort char name intn char temp inti j k for i 0 i0 k j if k i temp name i name i name k name k temp i 0 例对字符串排序 简单选择排序 main voidsort char name intn print char name intn char name Followme BASIC GreatWall FORTRAN Computer intn 5 sort name n print name n voidsort char name intn char temp inti j k for i 0 i0 k j if k i temp name i name i name k name k temp name 0 name 1 name 2 name 3 name 4 name GreatWall FORTRAN Computer Followme BASIC i 1 例对字符串排序 简单选择排序 main voidsort char name intn print char name intn char name Followme BASIC GreatWall FORTRAN Computer intn 5 sort name n print name n voidsort char name intn char temp inti j k for i 0 i0 k j if k i temp name i name i name k name k temp name 0 name 1 name 2 name 3 name 4 name GreatWall FORTRAN Computer Followme BASIC i 2 例对字符串排序 简单选择排序 main voidsort char name intn print char name intn char name Followme BASIC GreatWall FORTRAN Computer intn 5 sort name n print name n voidsort char name intn char temp inti j k for i 0 i0 k j if k i temp name i name i name k name k temp name 0 name 1 name 2 name 3 name 4 name GreatWall FORTRAN Computer Followme BASIC i 3 例对字符串排序 简单选择排序 main voidsort char name intn print char name intn char name Followme BASIC GreatWall FORTRAN Computer intn 5 sort name n print name n voidsort char name intn char temp inti j k for i 0 i0 k j if k i temp name i name i name k name k temp name 0 name 1 name 2 name 3 name 4 name GreatWall FORTRAN Computer Followme BASIC 多级指针定义 指向指针的指针一级指针 指针变量中存放目标变量的地址 例int p1 int p2 inti 3 p2 二级指针 指针变量中存放一级指针变量的地址 例int p inti 3 p 一级指针 单级间接寻址 二级指针 一级指针 目标变量 二级间接寻址 定义形式 存储类型 数据类型 指针名 如char p 例inti p p p是二级指针 不能用变量地址为其赋值 指针本身的存储类型 最终目标变量的数据类型 p是p间接指向对象的地址 p是p间接指向对象的值 例inti 3 int p1 int p2 p1 多级指针 例三级指针int p 四级指针char p 例一级指针与二级指针 includevoidswap int r int s int t t r r s s t main inta 1 b 2 p q p 2000 2002 2000 输出 1 2 例一级指针与二级指针 includevoidswap int r int s int t t r r s s t main inta 1 b 2 p q p 输出 1 2 例一级指针与二级指针 includevoidswap int r int s int t t r r s s t main inta 1 b 2 p q p 2000 2002 2000 输出 2 1 例一级指针与二级指针 includevoidswap int r int s int t t r r s s t main inta 1 b 2 p q p 输出 2 1 例用二级指针处理字符串 defineNULL0voidmain char p char name hello good world bye p name 1 printf o s p p p 2 while p NULL printf s n p 运行结果 644 goodbye 用 p可输出地址 o或 x 也可用它输出字符串 s p 二级指针与指针数组的关系int p与int q 10 指针数组名是二级指针常量p q p i是q i 的地址指针数组作形参 int q 与int q完全等价 但作为变量定义两者不同系统只给p分配能保存一个指针值的内存区 而给q分配10块内存区 每块可保存一个指针值 8 7指针变量与函数 函数是程序的基本单位 在函数操作中 函数的定义 函数调用 函数参数的传递 函数的返回值 在程序设计中必须进行设计考虑 在该操作中 可以使用指针变量来进行 指针型函数 返回指针值的函数 作用 函数返回的值 不是数值 而是地址函数定义形式 类型标识符 函数名 参数表 例int f intx inty 例指针函数实现 有若干学生成绩 要求输入学生序号后 能输出其全部成绩 main floatscore 4 60 70 80 90 56 89 67 88 34 78 90 66 float search float pointer 4 intn p inti m printf Enterthenumberofstudent scanf d 函数指针函数在编译时被分配的入口地址 用函数名表示 函数指针变量赋值 如p max 函数返回值的数据类型 专门存放函数入口地址可指向返回值类型相同的不同函数 指向函数的指针变量 函数指针 定义形式 数据类型 指针变量名 如int p 函数指针变量指向的函数必须有函数说明 函数调用形式 c max a b c p a b c p a b 对函数指针变量p n p p 无意义 不能省int p 与int p 不同 例用函数指针变量调用函数 比较两个数大小 main intmax int int inta b c scanf d d main intmax int int p inta b c p max scanf d d 用函数指针变量作函数参数 例用函数指针变量作参数 求最大值 最小值和两数之和 例写一个函数 求两个int型变量中居于较大值的变量的地址 2 3 2002 2000 例写一个函数 求两个int型变量中居于较大值的变量的地址 2002 例写一个函数 求两个int型变量中居于较大值的变量的地址 2 3 3 2 例写一个函数 求两个int型变量中居于较大值的变量的地址 不能返回形参或局部变量的地址作函数返回值 200A 命令行参数命令行 在操作系统状态下 为执行某个程序而键入的一行字符命令行一般形式 命令名参数1参数2 参数n main intargc char argv 命令行参数传递 带参数的main函数形式 C TC copy exe source ctemp c 有3个字符串参数的命令行 命令行中参数个数 元素指向命令行参数中各字符串首地址 形参名任意 第一个参数 main所在的可执行文件名 例输出命令行参数 test c main intargc char argv while argc 1 argv printf s n argv argc main intargc char argv while argc 0 printf s n argv 1 编译 链接test c 生成可执行文件test exe2 在DOS状态下运行 test exe所在路径下 例如 C TC test exe helloworld 运行结果 helloworld 运行结果 testhelloworld 8 8指针与动态内存分配 动态存储的概念动态内存分配是指在程序运行时为程序分配内存的一种方法 一般计算机设计语言都是通过指针实现这种访问 用一个指针指向动态分配得到的存储块 将存储块的地址存入指针 此后通过对指针的间接操作 就可以使用这个存储块了 这就是动态内存分配的原理 语言的动态存储管理方式C语言动态存储管理由一组标准库函数实现 它们包含在malloc h或stdlib h头文件中 共有四个 1 存储分配函数malloc调用形式 void malloc unsignedsize 功能 在内存的动态存储区中分配一块长度为 size 字节的连续区域 函数的返回值为该区域的首地址 若分配不成功 如size值过大 返回空指针 NULL 2 带计数和清零的动态存储分配函数calloc调用形式 void calloc unsignedn unsignedsize 功能 在内存动态存储区中分配n块长度为 size 字节的连续区域 分配时还把存储块全部清零 函数的返回值为该区域的首地址 若分配不成功 返回空指针 NULL 3 动态存储释放函数free调用形式 voidfree void ptr 功能 释放ptr所指向的一块内存空间 被释放区应是由malloc或calloc函数所分配的区域 free函数无返回值 因为释放总是成功的 4 分配调整函数realloc调用形式 void realloc void p unsignedsize 功能 本函数用于更改以前做过的存储分配 改变原来分配的存储空间的大小 函数返回值是新分配的存储空间的首地址 与原来分配的首地址不一定相同 例下列定义的含义 1 int p 3 2 int p 3 3 int p int 4 int p int 5 int p int 6 int p 3 int 7 int p 3 int 9 第九章 编译预处理 宏定义 文件包含 条件编译 编译 C编译系统对源程序进行 词法和语法分析 代码生成 优化 OBJ文件 编译预处理 编译前对源程序进行一些预加工 改善程序设计环境 模块化设计 编译预处理命令均以 开头 未尾不加分号可出现在程序的任何位置 其作用范围 出现点至所在源程序未尾 编译预处理 预处理功能C语言的预处理程序负责分析和处理以 为首字符的预处理控制行 预处理是在编译前进行的 预处理控制行主要有 宏替换 文件包含 条件编译和行控制等 宏替换define预处理命令不仅可以定义符号常量及字符串 而且也可以定义带参数的宏 1 简单的字符串替换一般形式 define宏标识符字符串通常 宏标识符 用大写字母表示 用空格分开 末尾不带 以换行符结束 例如 defineN10 defineTRUE 1 defineFALSE0 defineON1 defineOFF0 defineYES1 defineNO0 definePI3 14159 defineE2 7183 defineBLACK0 defineBLUE1 defineBEGIN defineEND 使用宏替换可增加程序的可移植型 例如 在程序中定义显示工作摸式为640 350 defineXMAX639 defineYMAM349当改为1024 1024时 可定义如下 defineXMAX1023 defineYMAX1023这就增加了图形程序对硬件环境的适应性 2 带参宏定义及宏调用与函数可带形式参数一样 宏标识符也可带有参数 在程序中可用实参数替带形式参数 实现宏调用 宏定义的一般格式 define宏标识符 形参数表 表达式宏调用的一般形式 宏标识符 实参数表 例如 defineMAX a b a b a bmain intx y x 10 y 20 printf Themaximumdatais d MAX x y 替换过程 printf Themaximumdatais d x y x y 1 宏定义格式 define宏名宏体宏名和宏体均为字符串 前者必须符合标识符命名规则 预处理时在程序中用宏体替换宏名 注意 可以用 undef宏名终止该宏名的作用范围 宏定义的撤消 undef宏标识符 定义符号常量 例一 defineM3 defineN M 1 defineNNN N 2main clrscr printf NN d NN printf 5 NN d n 5 NN 结果 NN 8 5 NN 40 讨论 如果第二行改为 defineNM 1 结果 NN 6 5 NN 18 带参数的宏定义格式 define宏名 参数表 宏体 例二 definePI3 14159 defines r PI r rmain floata 1 sum sum s a printf r 0f s f n a sum 结果 r 1 s 3 141590 带参数的宏定义 例三 definePT5 5 defines A PT A Amain inta 1 b 2 printf 4 1f n s a b 结果 9 5 讨论 注意s a b 不是函数 它不做任何计算 如果是函数 则s a b 为s 3 结果49 5 s a b 5 5 1 2 1 2 9 5 带参数的宏定义 例四 选择正确答案 include stdio h defineSUM y 1 ymain intx 2 printf d n SUM 5 x A 10B 11C 12D 15 结果 B 2 文件包含 include标准方式只按标准方式 系统存放C库函数头文件所在目录 查找所要包含的文件对TC 默认只在 tc include目录下查找 include 先在源文件所在目录找指定头文件 若无再按标准方式找 更保险 功能 把给定的包含文件的内容嵌入到一个源程序文件中 include 文件名 或 include 包含文件示意图 特别警示文件包含不可以彼此互相包含 否则容易造成嵌套定义函数 这是C语言不允许的 包含文件的存放地点 由文件路径和文件名指定 并放入双引号或尖括号中 系统约定的查找顺序是 双引号 源文件所在的当前文件目录 系统指定的标准目录尖括号 直接查找指定的标准目录Forexample 用户在当前目录中定义有 font h 文件 在编译程序的系统标准目录中也定义有一个同名 font h 文件 当用户需要使用自己定义的 font h 文件时 应使用 include font h 若使用 include将嵌入系统标准目录中的 font h 而不是用户自定义的头文件 3 条件编译 根据条件决定是否编译某一组语句 常用形式 如果标识符被定义过 如果标识符未被定义过 ifdef标识符 ifndef标识符程序段1程序段1 编译此程序段 else else else部分可省略 程序段2程序段2 反之 编译此程序段 endif endif 此处指标识符用 define等命令定义过 if表达式 如果表达式为真 程序段1 编译程序段1 else程序段2 否则 编译程序段2 endif 如果用 if表达式程序段1else程序段2 亦可实现以上功能 但程序段1 2均要编译 如果它们比较大 生成的exe文件就很大 3 条件编译 3 条件编译 例一 defineDEBUG0main inta 10 b 20 c clrscr c a b ifdefDEBUGprintf a d b d n a b endifprintf c d n c 结果 a 10 b 20c 0 讨论 如果 defineDEBUG呢 结果不变 如果没有 define行呢 只输出c 0 6 以下程序运行结果是 defineSQR x x xmain inta 10 k 2 m 1 a SQR k m printf d n a 2 3 条件编译 ifndef条件编译一般形式 ifndef标识符 如果表达式为真 程序段1 编译程序段1 else程序段2 否则 编译程序段2 endif作用是 如果标识符未被定义 则编译程序段1 否则编译程序段2 例如 3条件编译 defineUSA1main ifdefUSAprintf currencyisdollar n elseprintf currencyispound n ifndefFRANCEprintf franccan tbeused n endif 运行结果 currencyisdollarfranccan tbeused 1 C语言的预处理功能是由预处理程序实现的 预处理命令行都要以 开始 可以出现在源程序文件中的任何地方 通常把宏定义和文件包含放在文件的开头 2 宏定义中的简单字符串替换用于定义符号常量 带参数宏定义与宏调用与函数定义和函数调用类似 但宏的参数不存在数据类型 可适用于任何类型参数 包含文件是使用 include将要包含的文件插入该命令行的相应位置处 被包含的文件名必须用双引号或尖括号括起来 条件编译是按条件 分别按表达式值 标识符是否被定义 标识符是否未被定义三种情况 有选择地编译某个程序段 小结 第十一章复杂数据类型 结构体 线性链表 共用体与枚举 本章学习指导 在日常生活中 我们常会遇到一些需要填写的登记表 如住宿表 成绩表 通讯地址等 在这些表中 填写的数据是不能用同一种数据类型描述的 在住宿表中我们通常会登记上姓名 性别 身份证号码等项目 在通讯地址表中我们会写下姓名 邮编 邮箱地址 电话号码 E mail等项目 这些表中集合了各种数据 无法用前面学过的任一种数据类型完全描述 复杂数据类型 结构体 线性链表 共用体和枚举类型 包括它们的定义 变量的说明和应用 11 1结构体 问题 什么是结构体类型 什么是结构体变量 结构体类型与数组类型有什么区别和联系 11 2 1结构体类型的定义 结构体类型的定义形式为 struct类型名 成员项表列 例如包含上图中全部类型数据的结构体类型的定义如下 structperson 结构体类型名 charname 20 以下定义成员项的类型和名字 intage charsex longnum charnation charaddress 20 longtel 11 2 2结构体变量的定义和引用 结构体变量的说明有三种方法 1 用已定义的结构体类型名定义变量 例如 structpersonstudent worker 定义了两个结构体变量student和worker 用上面的结构体类型还可再定义变量 structpersonmen women 2 在定义结构体类型的同时定义结构体变量 例如 structperson charname 20 intage longtel student worker 一般的形式为 struct类型名 成员项表列 变量名表列 这样定义的结构体类型也还可多次使用 如 structpersonmen women 3 不定义结构体类型名 直接定义结构体变量 一般形式为 struct 成员项表列 变量名表列 结构体变量的引用 1 无嵌套的情况 引用结构体变量成员的形式为 结构体变量名 成员名 其中的 叫 结构体成员运算符 这样引用的结构体成员相当于一个普通变量 例如 student num 结构体变量student的成员num 相当于一个长整型变量 student name 结构体变量student的成员name 相当于一个字符数组名 在有嵌套的情况下 访问的应是结构体的基本成员 因为只有基本成员直接存放数据 且数据是基本类型或上面介绍的数组类型 引用形式为 结构体变量名 结构体成员名 结构体成员名 基本成员名即从结构体变量开始 用成员运算符 逐级向下连接嵌套的成员直到基本成员 不能省略 例如 student birthday year 基本成员year 相当于一个整型变量 2 有嵌套的情况 11 2 3结构体变量的赋值1结构体变量的初始化 在以上结构体变量的三种定义的同时都可以进行初始化赋值 例如 structpersonstud1 WangLi 18 M 34011 h 12 13BejingRoad 2098877 stud2 YuPing 19 F 34082 h 12 25HefeiRoad 5531678 注意初始化数据应与类型中的各个成员在位置上一一对应 对于嵌套的结构体类型变量 初始化是对各个基本类型的成员赋初值 例如 structpersonstudent WangLi 12 5 1974 M 340201 h 12 13BejingRoad 2098877 1 结构体变量的赋值 输入和输出 由于结构体各个成员的类型不同 对结构体变量赋值也只能对其成员进行 结构体变量的输入和输出也都只能对其成员进行 2 同一类型的结构体变量可相互赋值 同类型的两个结构体变量之间可以整体赋值 请比较数组之间不能整体赋值 stud1 stud2 2结构体变量的赋值 例11 2 输出结构体数据 includevoidmain structstu intnum char name charsex floatscore boy1 boy2 boy1 num 102 boy1 name Zhangping printf inputsexandscore n scanf c f 程序分析 本程序中用赋值语句给num和name两个成员赋值 name是一个字符串指针变量 用scanf函数动态地输入sex和score成员值 然后把boy1的所有成员的值整体赋予boy2 最后分别输出boy2的各个成员值 本例表示了结构变量的赋值 输入和输出的方法 11 2 4结构体数组 1 结构体数组的定义 有三种方法 1 先定义结构体类型 用结构体类型名定义结构体数组 如 structstud type charname 20 longnum intage charsex floatscore structstud typestudent 50 9 1 5结构体数组 2 定义结构体
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 生态农业基础试题及答案
- 禅城国企面试题及答案
- 医学生职业引导班会课件
- 构成艺术考试试题及答案
- 过河救人测试题及答案
- 未来汽车技术的探索试题及答案
- 谓词逻辑测试题及答案
- 电动汽车市场需求的变化与影响因素分析试题及答案
- 劳务外包外贸合同标准文本
- 产品代理合同范例
- 山东省济南市高新区2023-2024学年八年级下学期期末物理试题
- 供应商改善计划表
- DLT 5285-2018 输变电工程架空导线(800mm以下)及地线液压压接工艺规程
- 中国兔子行业上下游产业链全景、发展历程回顾及市场前景预测
- 10以上20以内加减法
- 急产分娩应急演练方案
- JBT 11699-2013 高处作业吊篮安装、拆卸、使用技术规程
- 24春国家开放大学《离散数学》大作业参考答案
- 2024年1月普通高等学校招生全国统一考试适应性测试(九省联考)化学试题(适用地区安徽)(试卷)
- 新能源综合能源系统的设计与优化
- 中国居民膳食指南(全)
评论
0/150
提交评论