c语言指针学习题,如图

C语言指针习题及答案_百度文库
赠送免券下载特权
10W篇文档免费专享
部分付费文档8折起
每天抽奖多种福利
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
C语言指针习题及答案
阅读已结束,下载本文需要
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,同时保存到云知识,更方便管理
加入VIP
还剩9页未读,
定制HR最喜欢的简历
你可能喜欢指针_百度百科
清除历史记录关闭
声明:百科词条人人可编辑,词条创建和修改均免费,绝不存在官方及代理商付费代编,请勿上当受骗。
[zhǐ zhēn]
在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的。
在中,指针有效地取代了在低级语言,如与机器码,直接使用通用的地方,但它可能只适用于合法地址之中。指针参考了中某个地址,通过被称为反参考指针的动作,可以取出在那个地址中存储的值。作个比喻,假设将电脑存储器当成一本书,一张内容记录了某个页码加上行号的便利贴,可以被当成是一个指向特定页面的指针;根据便利粘贴面的页码与行号,翻到那个页面,把那个页面的那一行文字读出来,就相当于是对这个指针进行反参考的动作。
在信息工程中指针是一个用来指示一个的计算机语言的变量或(CPU)中(Register)【用来指向该内存地址所对应的变量或数组】。指针一般出现在比较接近的语言,如汇编语言或。的语言如一般避免用指针。指针一般指向一个函数或一个变量。在使用一个指针时,一个程序既可以直接使用这个指针所储存的内存地址,又可以使用这个地址里储存的函数的值。另外,指针也指钟表中用来指示对应时间的部件。
使用指针来读取数据,在重复性操作的状况下,可以明显改善程序性能,例如在字符串,查取表格,控制表格及树状结构上。对指针进行复制,之后再解引用指针以取出数据,无论在时间或空间上,都比直接复制及访问数据本身来的经济快速。
指针的机制比较简单,其功能可以被集中重新实现成更抽象化的(reference)数据形别。许多编程语言中都支持某种形式的指针,最著名的是,但是有些编程语言对指针的运用采取比较严格的限制,如一般避免用指针,改为使用引用。
有两种含义,一是作为数据类型,二是作为实体。
指针作为实体,是一个用来保存一个内存地址的计算机语言中的变量。指针一般出现在比较底层的程序设计语言中,如C语言。高层的语言如Java一般避免用指针,而是引用。
指针作为数据类型,可以从一个函数类型、一个对象类型或者一个不完备类型中导出。从中导出的数据类型称之为被引用类型(referenced type)。指针类型描述了一种对象,其值为对被引用类型的实体的引用。
标准中规定,“指针”概念不适用于(不包含指向静态成员的指针)。C++标准规定,指针分为两类:
object pointer type:指向void或对象类型,表示对象在内存中的字节地址或空指针。
function pointer type:指代一个函数
指针信息工程
指针与C语言
大家都认为,c语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上。因此,说指针是c语言的灵魂,一点都不为过。同时,这种说法也让很多人产生误解,似乎只有C语言的指针才能算指针。不支持指针,在此不论。其实,语言本身也是支持指针的。从最初的pascal发展至今的,可以说在指针运用上,丝毫不会逊色于c语言的指针。
内存分配表
计算机中的内存都是的,就像你家的地址一样。在或者运行的时候,系统(可以不关心具体是什么,可能是,也可能是操作系统)开辟了一张表。每遇到一次声明(包括函数的传入参数的声明)都会开辟一个内存空间,并在表中增加一行纪录。记载着一些对应关系。(如图1所示)
Declaration | ID Name Address Length
int nP; | 1 nP 2000 2B
char myC | 2 myChar 2002 1B
int *myP | 3 myPointer 2003 2B
char *myPointer2; | 4 myPointer2 2005 2B
指针,是一个(unsigned int),它是一个以当前系统寻址范围为取值范围的整数。32位系统下寻址能力()是4G Bytes(0~2^32-1)表示长度为32bits(也就是4Bytes), unsigned int类型也正好如此取值。
例证(一)
例证就是程序1得到的答案和程序2的答案一致。(不同机器可能需要调整一下pT的取值)
#include &stdio.h&
char t='h';
putchar(*pT);
#include &stdio.h&
char t='h';
pT=(char *)1245048;
putchar(*pT);
加上(char *)是因为毕竟int 和char *不是一回事,需要,否则会有个警告。因为char *声明过的类型,一次访问1个sizeof(char)长度,double *声明过的类型,一次访问1个sizeof(double)长度。
在汇编里int 类型和指针就是一回事了。因为不论是整数还是指针,执行自增的时候,都是其值加一。如果上文声明char *pT;,汇编语言中pT自增之后值为1245049,C语言中pT++之后pT值为1245049。如果32 位系统中,上文声明int *pT;,汇编语言中pT 自增之后值为1245049,可是C 语言中pT++之后pT值为1245052。
为什么DOS下面的Turbo C,和Windows下VC的int类型不一样长。因为DOS是16位的,Windows是32位的,可以预见,在64位Windows 中编译,上文声明int *pT;,pT++之后pT值为1245056。
例证(二)
对于复杂的结构,如C语言的(汇编语言对应为Record类型)按顺序分配空间。(如图2所示)
int a[20];
typedef struct st
在32 位系统下,内存里面做如下分配(单位:H,16 进制);(如图3所示)
这就说明了为什么sizeof(pst)=16而不是8。编译器把结构体的大小规定为结构体成员中大小最大的那个类型的整数倍。
至于pT的存储,可以依例推得。总长为160,此不赘述。
有个问题,如果执行pT++,答案是什么?是自增16,还是160?别忘了,pT 是,不能加减。
所以,我们就可以
typedef struct BinTree
struct BinTree *LeftC
struct BinTree *RightC
用一个整数,代表一棵树的结点。把它赋给某个结点的LeftChild/RightChild 值,就形成了上下级关系。只要无法找到一个路径,使得A-&LC/RC-&LC/RC...-&LC/RC==A,这就构成了一棵。反之就成了图。
指针按值传递
C中是按值传递的,传入参数在子函数中只是一个初值相等的副本,无法对传入参数作任何改动。但实际编程中,经常要改动传入参数的值。这一点我们可以用传入参数的地址而不是原参数本身,当对传入参数(地址)取(*)运算时,就可以直接在内存中修改,从而改动原想作为传入参数的。
编程参数值
#include &stdio.h&
void inc(int *val)
printf(&%d& , a);
在执行inc(&a);时,系统在内存分配表里增加了一行“inc 中的val”,其地址为新地址,值为&a。操作*val,即是在操作a 了。
指针*和&运算
(*p)操作是这样一种运算,返回p 的值作为地址的那个空间的取值。(&p)则是这样一种运算,返回当时声明p 时开辟的地址。显然可以用对内存地址赋值。我们假设有这么两段内存地址空间,他们取值如下:(单位:H,16 进制)(如图4所示)
假设有这么一段代码:(假设开辟空间时p 被分配给了3001H、3002H 两个位置)
**p的值为多少?
**p=*(*(p))=*(*(2003H))=*(3000H)=3000H。
那么&&p、*(&p)和&(*p)又等于多少?
&&p=&(&(p))=&(3001H),此时出错了,3001H 是个常数怎么可能有地址呢?
*&p=*(&(p))=*(3001H)=2003H,也就是*&p=p。
&*p=&(*p)=&(3000H)=2003H,之前有人认为这个是不成立的,实际上&(3000H)是求存储3000H这个变量所在的内存地址,仍然是p的值。下面的代码是个很简单的例子:
#include&iostream&
using&namespace&
//环境vc6.0
int&main()
&&&&int&*a;
&&&&a=(int*)5;
&&&&cout&&(unsigned&int)&*a&&
输出的结果为5
指针另类*和&
两个地方要注意: 在程序声明变量的时候的*,只是表明“它是一个无符号整数,这个整数指向某个,一次访问sizeof(type)长度”。这点不要和(*)操作符混淆;
在C++程序声明变量的时候的&,只是表明“它是一个,这个引用声明时不开辟新空间,它在内存分配表加入新的一行,该行内存地址等于和调用时传入的对应参数内存地址”。
这点不要和(*)声明符,(&)操作符混淆。
指针双级指针
对于一棵树,我们通常用它的根节点地址来表示这棵树。这就是“擒贼先擒王”。找到了树的根,其每个都可以找到。但是有时候我们需要对树进行删除节点,增加节点操作,往往考虑到删除根节点,增加的节点取代原来的根节点作为新根节点的情况。为了修改根节点这个“整数”,我们需要退一步,使用这个“整数”的内存地址,也就是指向这个“整数”的指针。在声明时,我们用2 个*号,声明指向指针的指针。它的意思是“它是一个整数,这个整数指向某个内存地址,一次访问sizeof(int)长度,其值是一个整数,那个整数值指向某个内存地址,一次访问sizeof(BTree)长度。”。详见&数据结构&有关“树”的程序代码。由于存放的的地址,因此是指向指针变量的指针变量,或称二级指针变量。
指针指针的初始化
对指针进行初始化或赋值只能使用以下四种类型的值
1. 0 值常量表达式,例如,在编译时可获得 0 值的整型 const对象或字面值常量 0。
2. 类型匹配的对象的地址。
3. 另一对象末的下一地址。
4. 同类型的另一个有效指针。
把 int 型变量赋给指针是非法的,尽管此 int 型变量的值可能为 0。但允
许把数值 0 或在编译时可获得 0 值的 const 量赋给指针:
int zero = 0;
const int c_ival = 0;
int *pi = // error: pi initialized from int value of ival
pi =// error: pi assigned int value of zero
pi = c_// ok: c_ival is a const with compile-time value of 0
pi = 0;// ok: directly initialize to literal constant 0
除了使用数值 0 或在编译时值为 0 的 const 量外,还可以使用 C++ 语言从 C 语言中继承下来的预处理器变量 NULL,该变量在 cstdlib头文件中定义,其值为 0。如果在代码中使用了这个预处理器变量,则编译时会自动被数值 0 替换。因此,把指针初始化为 NULL 等效于初始化为 0 值
// cstdlib #defines NULL to 0
int *pi = NULL; // ok: equivalent to int *pi = 0;
指针与数组关系
:就是一个由指针组成的数组,那个数组的各个元素都是指针,指向某个内存地址。 char *p[10];//p是一个指针数组
:数组名本身就是一个指针,指向数组的首地址。注意这是一个常数。
char (*p)[10]//p是一个数组指针
:本身是一个指针,指向一个函数入口地址,通过该指针可调用其指向的函数,使用函数指针可实现。
#include &stdio.h&
void inc(int *val)
void (*fun)(int *);
fun=//fun是一个函数指针
(*fun)(&a);
printf(&%d& , a);
:本身是一个函数,其返回值是一个指针。
void * fun(void);// fun是一个指针函数
这个问题大家应该都碰到过,指针数组和数组指针,刚开始看时觉得还是能看懂,但是过些时又搞混了,最后发现还是没有真正理解。
下面就简单说说这两个概念:一:指针数组,顾名思义,就是说的首先是一个数组吧,然后数组的元素是指针而已。说明形式为:type *pointer_array[constant1][constant2]...[constantn]; 例如:int *pai[4]; 由于‘*’是自右向左结合,因此从右向左看,首先看到[4]说明是一个数组,是一个包含4个元素的数组,然后看到‘*’,显然是指针类型,由此可以看出数组中存放的是指针而不是一般的类型。同理,char *pac[2][3]是包含有6个元素,每一个元素都是一个字符型指针。再来说说他们的初始化: int *pai[3];既然是一个包含4个整形指针的数组那么其对应的将是一个二维整形数组,因为一个整形指针对应一个一维整形数组。那我就用一个二维整形数组来初始化它,事实上一般也都是这么做的,这里有一个二维数组,int arr[3][2]={{1,2},{3,4},{5,6}},一个三行两列的整形数组,注意这里的行必须和你的指针数组的维数一致,否则是不允许的,不信你可以试试。这个初始化有很多种选择,以下只列举常见的两种:第一种也是很好理解的: for(int i=0;i&3;i++) pai[i]=arr[i]; 显然arr[i]是每一行的首地址,相当于一个一维数组的数组名,如是把它送给一个整形指针pai[i]是理所当然的了。
第二种方法:在说明数组指针时就初始化:int (*ap)[2]={{1,2},{3,4},{5,6}};
注意:不能将二维数组的数组名赋给指针数组的数组名,pai=arr(错),因为两者的类型不一致,二维数组名的类型是指向int[][]型的指针,而指针数组的的数组名是指向int *[]类型的指针。
在c/c++语言中,指针数组最常用的场合就是说明一个字符串数组。即说明一个数组,它的每个元素都是一个字符串。
二:数组指针:指向一个数组的指针。说明形式为:type (*pointer_array)[constant1][constant2]...[constantn]; 注意这里的圆括号是必须就将这是由于方括号[],较指针说明符“*”的优先级高,若无此圆括号,编译器将把上述说明解释成成了一个数组指针。例如:int (*ap)[2]; 这样就说明了一个指向包含有2个元素的整形数组的数组指针,听起来确实有点别扭。不过仔细分析应该还是能理解的,就是说ap是一个指针,而它指向的对象是一个指针,注意不要将它和一个指向一个整形变量的指针搞混了。同样以一个二维数组来说明其初始化问题, int arr[3][2]={{1,2},{3,4},{5,6}};注意这里的列数必须和数组指针所指的数组的列数相同。第一种方法: ap= 为什么这里能这样将二维数组名送给ap呢,你可以这样理解,二维数组不就可以看成是一维数组的数组吗,而一个数组指针它指向的内容就是一个一维数组,那么你就可以把这个数组指针当做是一个数组名,只不过这个数组里的元素不是像int,char之类型的,而是一个数组,这样你就可以把它和二维数组的数组名联系在一起了。
第二种方法: ap=&arr[0]; 这里arr[0]其实就是一维数组的数组名,将它的地址给ap是很自然的,因为ap本来就是指向一个一维数组的。注意这里不能这样初始化:int (*a)[2]={{1,2},{3,4},{5,6}};大家可以想想为什么。当然他们也可以动态赋值,由于篇幅就不探讨了。
指针与“引用”的区别
C++编程中指针与引用的区别
一、指针和引用的区别
(1)引用总是指向一个对象,没有所谓的 null reference .所有当有可能指向一个对象也有可能不指向对象则必须使用 指针.
由于C++ 要求 reference 总是指向一个对象所以 reference要求有初值.
String & rs = string1;
由于没有所谓的 null reference 所以在使用前不需要进行测试其是否有值,而使用指针则需要测试其的有效性.
(2)指针可以被重新赋值而reference则总是指向最初或地的对象.
(3)必须使用reference的场合. Operator[] 操作符 由于该操作符很特别地必须返回 [能够被当做assignment 赋值对象] 的东西,所以需要给他返回一个 reference.
(4)其实引用在函数的参数中使用很经常.
void Get***(const int& a) //这样使用了引用又可以保证不修改被引用的值
★ 相同点:
1. 都是地址的概念;
指针指向一块内存,它的内容是所指内存的地址;引用是某块内存的别名。
1. 指针是一个实体,而引用仅是个别名;
2. 引用使用时无需(*),指针需要解引用;
3. 引用只能在定义时被初始化一次,之后不可变;指针可变;
引用“从一而终”
4. 引用没有 const,指针有 const,const 的指针不可变;
5. 引用不能为空,指针可以为空;
6. “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;
typeid(T) == typeid(T&) 恒为真,sizeof(T) == sizeof(T&) 恒为真,
但是当引用作为成员时,其占用空间与指针相同(没找到标准的规定)。
7. 指针和引用的自增(++)运算意义不一样;
二、C++中指针传递与引用传递(进一步整理)
从概念上讲。指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变。
而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量)。
在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的:
指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的处理,即在中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。(这里是在说实参指针本身的地址值不会变)
而在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
引用传递和指针传递是不同的,虽然它们都是在被调函数栈空间上的一个局部变量,但是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量。而对于指针传递的参数,如果改变被调函数中的指针地址,它将影响不到主调函数的相关变量。如果想通过指针参数传递来改变主调函数中的相关变量,那就得使用指向指针的指针,或者指针引用。
为了进一步加深大家对指针和引用的区别,下面我从编译的角度来阐述它们之间的区别:
程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以改),而引用对象则不能修改。
最后,总结一下指针和引用的相同点和不同点:
★相同点:
●都是地址的概念;
指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。
★不同点:
●指针是一个实体,而引用仅是个别名;
●引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;
●引用没有const,指针有const,const的指针不可变;(具体指没有int& const a这种形式,而const int& a是有 的, 前者指引用本身即别名不可以改变,这是当然的,所以不需要这种形式,后者指引用所指的值不可以改变)
●引用不能为空,指针可以为空;
●“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;
●指针和引用的自增(++)运算意义不一样;
●引用是类型安全的,而指针不是(引用比指针多了类型检查)
指针可以用来有效地表示复杂的数据结构,可以用于函数并达到更加灵活使用函数的目的.使C语言程序的设计具有灵活、实用、高效的特点。
谭浩强.《c程序设计》.清华大学出版社:清华大学出版社,2010.6:220
.维基百科[引用日期]
C++Primer第四版中文版
.CSDN 程序员网.[引用日期]
.CSND程序员网.[引用日期]
.ITeye 技术网站.[引用日期]
中国电子学会(Chinese Instit...
提供资源类型:内容
清除历史记录关闭C语言指针经典练习题-及答案_百度文库
赠送免券下载特权
10W篇文档免费专享
部分付费文档8折起
每天抽奖多种福利
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
C语言指针经典练习题-及答案
阅读已结束,下载本文需要
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,同时保存到云知识,更方便管理
加入VIP
还剩8页未读,
定制HR最喜欢的简历
你可能喜欢C语言中的指针和内存泄漏
对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏。这些的确是消耗了开发人员大多数调试时间的事项。指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是一旦您了解了指针及其关联内存操作的基础,它们就是您在 C 语言中拥有的最强大工具。
本文将与您分享开发人员在开始使用指针来编程前应该知道的秘密。本文内容包括:
●导致内存破坏的指针操作类型
●在使用动态内存分配时必须考虑的检查点
●导致内存泄漏的场景
如果您预先知道什么地方可能出错,那么您就能够小心避免陷阱,并消除大多数与指针和内存相关的问题。
什么地方可能出错?
有几种问题场景可能会出现,从而可能在完成生成后导致问题。在处理指针时,您可以使用本文中的信息来避免许多问题。
未初始化的内存
在本例中,p已被分配了 10 个字节。这 10 个字节可能包含垃圾数据,如图 1所示。
char *p = malloc ( 10 );
图1.垃圾数据
如果在对这个p赋值前,某个代码段尝试访问它,则可能会获得垃圾值,您的程序可能具有不可预测的行为。p可能具有您的程序从未曾预料到的值。
良好的实践是始终结合使用memset和malloc,或者使用calloc。
char *p = malloc (10);
memset(p,’’,10);
现在,即使同一个代码段尝试在对p赋值前访问它,该代码段也能正确处理Null值(在理想情况下应具有的值),然后将具有正确的行为。
由于p已被分配了 10 个字节,如果某个代码片段尝试向p写入一个 11 字节的值,则该操作将在不告诉您的情况下自动从其他某个位置“吃掉”一个字节。让我们假设指针q表示该内存。
图2.原始 q 内容
图3.覆盖后的 q 内容
结果,指针q将具有从未预料到的内容。即使您的模块编码得足够好,也可能由于某个共存模块执行某些内存操作而具有不正确的行为。下面的示例代码片段也可以说明这种场景。
char *name = (char *) malloc(11);
// Assign some value to name
memcpy ( p,name,11); // Problem begins here
在本例中,memcpy操作尝试将 11 个字节写到p,而后者仅被分配了 10 个字节。
作为良好的实践,每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。一般情况下,memcpy函数将是用于此目的的检查点。
内存读取越界
内存读取越界 (overread) 是指所读取的字节数多于它们应有的字节数。这个问题并不太严重,在此就不再详述了。下面的代码提供了一个示例。
char *ptr = (char *)malloc(10);
char name[20] ;
memcpy ( name,ptr,20); // Problem begins here
在本例中,memcpy操作尝试从ptr读取 20 个字节,但是后者仅被分配了 10 个字节。这还会导致不希望的输出。
内存泄漏可能真正令人讨厌。下面的列表描述了一些导致内存泄漏的场景。
●重新赋值我将使用一个示例来说明重新赋值问题。
char *memoryArea = malloc(10);
char *newArea = malloc(10);
这向如下面的图 4所示的内存位置赋值。
图4.内存位置
memoryArea和newArea分别被分配了 10 个字节,它们各自的内容如图 4所示。如果某人执行如下所示的语句(指针重新赋值)……
memoryArea = newA
则它肯定会在该模块开发的后续阶段给您带来麻烦。
在上面的代码语句中,开发人员将memoryArea指针赋值给newArea指针。结果,memoryArea以前所指向的内存位置变成了孤立的,如下面的图 5所示。它无法释放,因为没有指向该位置的引用。这会导致 10 个字节的内存泄漏。
图5.内存泄漏
●在对指针赋值前,请确保内存位置不会变为孤立的。
●首先释放父块假设有一个指针memoryArea,它指向一个 10 字节的内存位置。该内存位置的第三个字节又指向某个动态分配的 10 字节的内存位置,如图 6所示。
图6.动态分配的内存
free(memoryArea)
如果通过调用 free 来释放了memoryArea,则newArea指针也会因此而变得无效。newArea以前所指向的内存位置无法释放,因为已经没有指向该位置的指针。换句话说,newArea所指向的内存位置变为了孤立的,从而导致了内存泄漏。
每当释放结构化的元素,而该元素又包含指向动态分配的内存位置的指针时,应首先遍历子内存位置(在此例中为newArea),并从那里开始释放,然后再遍历回父节点。
这里的正确实现应该为:
free( memoryArea-&newArea);
free(memoryArea);
返回值的不正确处理
有时,某些函数会返回对动态分配的内存的引用。跟踪该内存位置并正确地处理它就成为了calling函数的职责。
char *func ( )
return malloc(20); // make sure to memset this location to ‘’…
void callingFunc ( )
func ( ); // Problem lies here
在上面的示例中,callingFunc()函数中对func()函数的调用未处理该内存位置的返回地址。结果,func()函数所分配的 20 个字节的块就丢失了,并导致了内存泄漏。
归还您所获得的
在开发组件时,可能存在大量的动态内存分配。您可能会忘了跟踪所有指针(指向这些内存位置),并且某些内存段没有释放,还保持分配给该程序。
始终要跟踪所有内存分配,并在任何适当的时候释放它们。事实上,可以开发某种机制来跟踪这些分配,比如在链表节点本身中保留一个计数器(但您还必须考虑该机制的额外开销)。
访问空指针
访问空指针是非常危险的,因为它可能使您的程序崩溃。始终要确保您不是在访问空指针。
本文讨论了几种在使用动态内存分配时可以避免的陷阱。要避免内存相关的问题,良好的实践是:
●始终结合使用memset和 malloc,或始终使用calloc。
●每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。
●在对指针赋值前,要确保没有内存位置会变为孤立的。
●每当释放结构化的元素(而该元素又包含指向动态分配的内存位置的指针)时,都应首先遍历子内存位置并从那里开始释放,然后再遍历回父节点。
●始终正确处理返回动态分配的内存引用的函数返回值。
●每个malloc都要有一个对应的 free。
●确保您不是在访问空指针。
来自:IBM developerWorks
链接:http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/
责任编辑:
声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
今日搜狐热点

我要回帖

更多关于 c语言指针面试题 的文章

 

随机推荐