2024年1月2日发(作者:新冠肺炎疫情最新情况)
内存单元的地址程序中定义了一个变量后系统要根据这个变量的类型在编译时给它分配内存单元。许多微机的C系统:给整型变量分配2 个字节给实型变量分配4 个字节给字符型变量分配1 个字节。内存区的每一个字节有一个编号它就是内存单元的地址。10.1 地址和指针的概念内存单元的地址与内存单元的内容是两个不同的概念:这种按变量地址存取变量值的方式称为“直接访问”方式。内存用户数据区...2000 3
变量i2002 6 变量j2004 9 变量k…定义整型变量ijk后编译时系统分配2000和2001两个字节给i2002和2003给j2004和2005给k。对变量值的存取通过地址进行。执行printf“d”i时根据变量名与地址的对应关系找到i的地址2000从2000开始的两个字节中取出数据3把它输出。执行scanf“d”ampi时把键盘输入的值送到地址为2000开始的整型存储单元中。执行kij时是从地址为2000和2001两个字节取出i的值3再从2002和2003取出j的值6相加后将其和9送到k所占用的2004和2005字节单元中。“间接方式是先找到存放“i的地址”的单元地址3010、3011从中取出i的地址2000然后到2000、2001字节取出i的值3。2000 变量i3010 变量2000 ......C语言可以定义一种用来存放地址的特殊的变量。例如i_pointer是这样的变量它被分配3010和3011字节下面语句将变量i的地址存放在i_pointer中i_pointerampii_pointer的值是2000即变量i的起始地址是2000。将数值3送到变量i 中有两种方法1、直接访问。将3送到变量i 所占的单元中。2、间接访问。将3送到i_pointer所“指向”的单元中。i 32000i_pointer
i320002000i_pointer中的值是20002000是i 的地址通过i_pointer能知道i 的地址从而找到变量i 的内存单元。3 、两种访问方式的比较两种访问方式之间的关系可以用某人甲系统要找某人乙变量来类比。一种情况是甲知道乙在何处直接去找就是即直接访问。另一种情况是甲不知道乙在哪但丙指针变量知道此时甲可以这么做先找丙从丙处获得乙的去向然后再找乙即间接访问。由于通过地址能找到所需的变量单元可以说地址“指向”该变量单元。因此C语言中将地址形象化地称为“指针”。专门用来存放变量地址即指针的变量叫“指针变量”。上面的i_pointer是一个指针变量。指针变量的值是指针地址。10.2 变量的指针和指向变量的指针变量用“”符号表示“指向”例如i_pointer是一个指针变量 i_pointer是i_pointer所指向的变量。 i_pointer也是代表一个变量执行“i_pointerampi”后它和变量i 是同一回事下面两个语句作用相同i3
i_pointer3i_pointer i_pointer20003 i2000变量的指针就是变量的地址。存放变量地址的变量是指针变量。用来指向另一个变量。10.2.1 定义一个指针变量指针变量不同于整型变量和其他类型的变量它是用来存放地址的。必须将它定义为“指针类型”。指针变量定义的一般形式基类型指针变量名“基类型”是用来指定该指针变量可以指向的变量类型。例如int i j int pointer_1 pointer_2 pointer_1ampi pointer_2ampj
float pointer_3 char pointer_4 ①标识符前面的“”表示该变量为指针变量。但指针变量名是pointer_1 pointer_2 而不是ponter_1 pointer_2。②必需指定基类型。一个指针变量只能指向某一个类型的变量。例如前面的pointer_1只能指向整型变量不能指向其它类型变量。int ponter_1 可以理解为ponter_1是整型变量ponter_1是ponter_1指向的变量。就象int a 定义a为整型变量一样。执行pointer_1 ampi后ponter_1就指向i i 和pointer_1是同一回事。只有同一类型的变量的地址才能放到指向该类型变量的指针变量中。定义指针变量时注意两点10.2.2 指针变量的引用与指针有关的两个运算符amp 是取地址运算符 是指针运算符例如ampa为变量a的地址p是指针变量p所指向的变量。特别注意①当定义指针变量时指针变量的值是随机的不能确定它具体的指
向必须为其赋值后才有意义。②指针变量的类型必须与其存放的变量类型一致即只有整型变量的地址才能放到指向整型变量的指针变量中。记住如果一个指针变量中存放的是某一个变量的地址那么指针变量就指向那个变量。例10.1 通过指针变量访问整型变量main int a100b10 int pointer_1pointer_2 pointer_1ampa pointer_2ampb
printf“ddn”abprintf“ddn”pointer_1 pointer_2运行结果为100 10100 10可以这样来理解指针和指针变量1.指针是一种特殊的数据类型它是内存地址2.指针变量是一种变量这种变量中存放的数据是内存地址即指针型数据。3.指针变量与其所指向的变量之间的关系如图:i_pointer i_pointeri2000i i_pointerampi i_pointer i 3 i_pointer320003说明在程序中用“ ”符号表示“指向”。例如 i_pointer代表指针变量而i_pointer是i_pointer
所指向的变量见上图。可以看到i_pointer是一个变量它和变量i是同一回事。下面两个语句作用相同①i3②i_pointer 3其中第二条语句的含义是将3赋值给指针变量i_pointer所指向的变量i_pointer.例1p1ampap2ampbp2ampp1/将ampaa的地址赋给p2/p2由指向b改为指向a。即p1和p2都指向a。p1 a p1 a pp2 b p2 bP1 p2原来的指向p2
重新赋值后p1 p2现在的指向ampaampbampaampaamp和 这两个运算符的优先级别相同但按自右而左的方向结合。例2: ampa的含义ampa所指向的变量即ampa与a等价。如pointer_1 ampaampa1/与pointer_11或a1作用一样/例3: pointer_1 相当于a
pointer_1 相当于pointer_1 88apointer-199输入a和b两个整数按先大后小的顺序输出a和b。main int p1p2pab scanf“dd”ampaampbp1ampap2ampb ifaltbpp1p1p2p2p /交换指针变量p1p2的值而变量ab的值并未改变/printf“adbdn”abprintf“maxd mindn”p1p2运行时输入5和9输出为a5 b9max9 min5p1 ap ampa 5p2 bampb 9ampap1 ap ampb
5p2 bampa 910.2.3 指针变量作为函数参数函数的参数可以是指针类型。作用是将一个变量的地址传送到另一个函数中。例10.3 对输入的两个整数按由大到小顺序输出。swapint p1 int p2 int temptempp1p1p2p2tempmain int abint
pointer_1pointer_2scanf“dd”ampaampbpointer_1ampa
pointer-2ampbifaltbswappointer_1pointer_2printf“nd d n” a b输入:5 9输出:9 5⑴如果将例10.3中的swap函数改成下面形式则是错误的。swapint p1int p2 int temp
tempp1p1p2p2temptemp是temp所指向的变量但temp中并无确定的地址它的值是不可预见的。对temp赋值可能会破坏系统的正常工作状态。⑵swap函数改成下面形式也不能实现a和b的互换。swapint xint yint temptempxxyytempx和y的值是换了但main函数中的a和b却没有换。这是由于“单向传送”的“值传递”方式形参值x和y的改变无法传给实参a和b。几种情况分析总结通过调用函数得到n个要改变的值在主调函数中使用这些值的4个步骤①在主调函数中设n个变量用n个指针变量指向它们②将指针变量作实参将这n个变量的地址传给所调用的函数的形参③通过形参指针变量改变这n个变量的值④主调函数使用这些改变了值的变量。⑶可以象例10.3那样用指针变量作函数参数在函数执行过程中使指针变量所指向的变量值发生变化函数调用结束后这些值的变化依然保留下来从而实现“调用函数改变变量的值在主调函数如main函数中使用这些改变了的值”。⑷注意:不能企图通过改变指针形参的值而使指针实参的值也改变。swapint p1 int p2 int p pp1 p1p2 p2pmain int abint
pointer_1pointer_2scanf“dd”ampaampbpointer_1ampa pointer_2ampbifaltb
swappointer_1pointer_2printf“nddn”pointer_1pointer_2程序作者的意图是交换pointer_1和pointer_2 的值使pointer_1指向值大的变量。但是办不到。运行程序输入
“59”输出仍是“59”。原因是C语言中实参变量和形参变量之间的数据传递是单向的“值传递”方式。指针变量作函数参数时也要遵循这一规则。记住调用函数不能改变实参指针变量的值。但可改变实参指针变量所指变量的值。在第8章学习函数时知道调用函数只能得到一个返回值即函数值。而运用指针变量作参数可以得到多个变化了的值。例10.4输入a、b、c三个整数按由大到小的顺序输出。swapint pt1 int pt2
int p ppt1 pt1pt2 pt2p exchangeq1 q2 q3int q1 q2 q3if q1ltq2 swapq1 q2if q1ltq3
swapq1q3if q2ltq3 swapq2q3 main int abc p1p2p3scanf“ddd” ampa ampb ampcp1ampa
p2ampb p3ampcexchangep1 p2 p3printf“ndddn”a b c 数组的指针是指数组的起始地址。数组元素的指针是数组元素的地址。10.3.1 指向数组元素的指针这种指针变量的定义与前面介绍的指向变量的指针变量相同。例如int a10int p pampa0C语言规定数组名代表数组的首地址即数组第一个元素的地址。因此下面两个语句等价pampa0
pa 定义指针变量时可以赋初值。如int a10 int pampa0 或int pa a0Pampa0a9a可以通过指针给数组元素赋值。int a10int ppampa3 p1/相当于a31/C语言规定若p指向数组中的一个元素则p 1指向数组的下一个元素。例如若数组元素是实型每个元素占4个字节则p1使p的原值地址加4个字节。p1所代表的地址实际上是p的原地址加d d是一个数组元素所占的字节数整型d2实型d4字符型d1。对一维数组讲如果p的初值为ampa0则1pi和ai就是ai的地址pi和ai指向a数组的第i个元素。pi和ai的实际地址是aid。2pi或ai是指针pi或ai所指向的数组元素即ai。实际编译时将数组元素ai处理成ai找出该单元中的内容。例如a数组的首地址为1000若数组是int则a3的地址是1000321006从1006地址所标志的整型单元中取出的值就是a3的值。3指向数组的指针变量p也可以带下标如pi与pi等价。a0 a1 a2aia9a 数组p p1a1 piai p9a9引用一个数组a的元素可以用3种方法1下标法如形式ai。2 首地址加偏移量如ai其中a为数组名是数组的首地址。3指针法pi。p是指针变量 pa。例10.5 整型数组a有10个元素可用3种方法输出各元素值。1、下标法main int a10int ifori0ilt10i scanf“d”ampaiprintf“n”for i0ilt10i printf“d”ai 3、指针法main int a10 p ifor i0ilt10iscanf“d”ampaiprintf“n”for paplta10pprintf“d”p2、首地址加偏移量main int a10 ifori0ilt10iscanf“d”ampaiprintf“n”for i0ilt10i printf“d”ai使用指针变量要注意以下4个问题1指针变量可以使自身的值发生改变。如p使p的值不断改变。如果将第3种方法的后两行改为下面形式是错误的for pa altp10 aprintf“d”a因为a是数组名它是数组首地址它的值在程序运行期间是固定不变的。a是无法实现的。2要注意指针变量的当前值。例10.6输出a数组的10个元素。main int p i
a10pafori0ilt10iscanf“d”pprintf“n” fori0ilt10ipprintf“d”p 运行程序输出结果不是a数组的元素值。原因是第1个for循环后p已指向a数组的末尾因此执行第2个for循环时p的起始值不是ampa0了。解决的办法是在第2个for循环前加一个语句“pa”使p的初始值为ampa0。pa3从2可以看到虽然定义数组包含10个元素用p指向数组元素但指针变量可以指到数组以后的内存单元。如果有a10C不认为非法把它按a10处理。在定义数组时可以不定义数组的长度。如将2中的定义改为“int p i a ”不指定a数组长度用p来指向数组各个元素程序运行结果相同。4注意指针变量的运算。如果先使p指向数组a即pa则①pp1 p指向a下一元素即a1。若再执行p取出下一元素a1的值。②p 等价于p作用是先得到p指向的变量值即p然后再使p1赋给p。③p与p作用不同。前者是先取p的值再使p加1。后者是先使p加1再取p。④p表示p所指向的元素值加1。即a0若a03则a0 的值为4。⑤如果p当前指向a数组中第i 个元素则 p --相当于ai--先取p值作“”
运算再使p自减。p相当于ai先使p自加再作运算。 --p 相当于a--i先使p自减再作运算。将和--运算符用于指针变量可使指针变量自动向前或向后移动指向上一个或下一个数组元素。例pa while plta100 printf“d” p例若有定义int b5则以下对b数组元素的正确引用是Aampb5Bb2Cb2Db2例若有以下语句则对X数组元素的引用不正确的是int
x123456ptrptrxA--ptrBptr--CptrDptr例若有定义int c5pc则以下对C数组元素地址的正确引用是Ap5BcCampc1Dampc0数组名可以作函数的形参和实参。如main f int arr
int n int array10 ……farray10 ………… 数组名代表数组的首地址数组名作实参实际是把数组的首地址传给形参。这样实参数组和形参数组共占同一段内存。形参数组的元素值发生变化时实参数组的元素值相应变化。数组名作为形参时C编译系统是将行参数组名作为指针变量进行处理的。故在函数中定义Rev_arrint x int n 与Rev_arrint x int n是等价的。10.3.3 数组名作函数参数变量名作函数参数与数组名作函数参数的比较实参类型变量名数组名要求形参的类型变量名数组名或指针变量传递的信息变量的值数组的起始地址通过函数调用能否改变实参的值不能能例10.7将a数组中n个整数按相反顺序存放。void invint x int n int tijmn-1/2fori0iltmijn-1-i
txixixjxjtreturn main int i a1printf“The original
array:n”fori0ilt10iprintf“d ”aiprintf“n” inva 10printf“The array has been invertde:n”for
i0ilt10iprintf“d ”aiprintf“n” 37911067542imj例10.7 解法2:将函数inv中的形参x改成指针变量。P.219void invint xint nint p tij/给m i j p 赋初值/mn-1/2ixjxn-1pxmforiltpi
j--tiijjtreturn main int i a1printf“The original array:n”for i0ilt10i
printf“d“aiprintf“n” inva10printf“The array has been inverted:n”for i0ilt10i printf“d“ai
printf“n” a0a1a2a3a4a5a6a7a8a9a 数组ix37911pxm 0 6754j 2例10.8从10个数中找出其中最大值和最小值。int max minvoid max_min_valueint array int n int
parray_endarray_endarraynmaxminarrayforparray1pltarray_endpifpgtmax maxpelse
ifpltmin minpreturnmain int i number10printf“enter 10 datan”for
i0ilt10iscanf“d”ampnumberimax_min_valuenumber10printf“nmaxdmindn”max min函数max_min_value中求出的最大值和最小值放在全局变量max和min中。或array例10.8中的实参可以不用数组名而用指针变量传递地址。int max min / 全局变量/void
max_min_valueint arrayint nint parray_endarray_endarraynmaxminarrayfor
parray1pltarray_endpif pgtmax maxpelse if pltmin minpreturn main int i
number10ppnumberprintf“enter 10 datan”fori0ilt10ipscanf“d”pprintf“the 10
data :n”forpnumberi0ilt10i
pprintf“d”ppnumbermax_min_valuep10printf“nmaxdmindn”maxmin归纳起来若想在函数中改变实参数组元素的值实参和形参的对应关系有以下4种情况1形参和实参都用数组名main f int x int nint a10 n …… fa 10 ………… 形参x和实参a都是数组名x和a共用一段内存单元。2实参用数组名形参用指针变量main fint xint nint
a10 …… fa 10………… 函数开始执行时x指向a0即xampa0通过x值的改变可以指向a数组的任一元素。3实参形参都用指针变量main fint xint nint a10p
pa …… ……fp 10...….…… p的初值是ampa0。将p传给形参指针变量x通过x值的改变可以使x指向数组a的任一元素。4实参为指针变量形参为数组名main fint x
int n int a10 p pa …… ……fp 10 …… 先使p指向a数组即pa再将p的值传给形参x使形参数组x和a数组共用同一段内存单元。形参数组x元素变化使a数组元素也相应变化。例10.9用实参指针变量改写例10.7void invint xint nint p m ti j mn-1/2ix jxn-1
pxmfor iltpij--tiijjtreturn main int iarr10parrprintf“The original
array:n”fori0ilt10ipscanf“d”pprintf“n”parr invp 10printf“The array has been
inverted:n”for parr pltarr10 pprintf“d”pprintf“n”例10.10用选择法对10个数由大到小排序。main int pia10pafori0ilt10iscanf“d”ppasortp10forpai0ilt10iprintf“d”p psortint x
int nint ijkt fori0 iltn-1 ikiforji1 jltn jifxjgtxk kjif k itxi xixk xkt 例10.10中的sort函数等价于sortint x int n int i j k t fori0 iltn-1 ikifor ji1 jltn j ifxjgtx.
更多推荐
变量,指针,地址,数组
发布评论