c语言动态分配内存 有关char的动态内存分配 问题?

Posts - 79,
Articles - 1,
Comments - 0
22:31 by dream_er, ... 阅读,
C语言中的动态内存分配详解
C语言中最难也最重要的要数指针这一章了,对指针的熟练程度决定了你对语言的学习的好坏程度,笔者自己在学习语言时,在指针上花费的时间几乎等于学习其他基础知识的时间,所以,对指针这一章有着自己独特的见解和学习方法。
指针,简单来说其作用就是用来操作内存的,而语言中动态内存分配就是一大难点,所以我今天特别来讲一下关于动态内存分配的问题,先给出代码:
#include&stdio.h&
#include&stdlib.h&
struct&student
char&name[20];
struct&student&*
int&count=0;
void&main()
struct&student&*head,*New,*O
head=New=Old=(struct&student&*)malloc(sizeof(struct&student));
printf(&请输入学号姓名和分数空格隔开
scanf(&%d&%s&%f&,&New-&id,New-&name,&New-&score);
while(New-&id!=0)
while(New-&id!=0)
count++;
if(count==1)
New-&next=NULL;
New-&next=NULL;
Old-&next=N
New=(struct&student&*)malloc(sizeof(struct&student));
printf(&请输入学号姓名和分数空格隔开
scanf(&%d&%s&%f&,&New-&id,New-&name,&New-&score);
free(New);
代码分析:
由于过程中要使用函数故先要导入这个头文件,然后先定义指向结构体变量的指针,用于指向链表的头结点,用于指向新分配的内存的地址,用于指向新分配的内存的上一个内存的地址,代码行,将和,都被赋值给第一次分配的内存的地址,算是对指针变量的初始化吧,接下来给内存空间赋值,然后就是动态内存的核心部分,也算是比较难以理解的部分吧,定义一个全局变量用于计数分配内存的次数,在这个循环中,默认了输入的学生的不能为零,如果为零,则会跳出循环,结束程序,否会则继续执行。循环中,先给自加一,表示已经分配了一次内存空间,然后对进行判断,当时,由于前面只分配了一次内存,所以不存在新旧内存之分,故只用给分配的内存中的值赋为空,即使末结点指向为空,由于上面已经对和已经初始化,故在此不需要对其再次进行赋值操作。当语句执行完后,就再次进行内存分配操作,接着,由于自加,已经大于,所以会执行后面的语句,先对新分配的内存中的赋值,使其指向为空,即如上的,每次使末节点指向为空,然后,将的指向新分配的内存空间的头结点,这就是链表链的部分。然后,将的值赋给,算是新老交换把,这里比较难以理解,建议读者可以找张纸画一画,就可以理解了。c语言指针、动态分配内存例题
void getMemeory1(char *p)
&& p = (char
*)malloc(100*sizeof(char));
char * getMemeory2()
&& char p[100] = "Hello
int main()
&&& char *str1 =
getMemeory1(str1);
&& &strcpy(str1,
"Hello world");
&&&&printf("str1
= %s\n", str1);
&&& char *str2 =
&& &str2 =
getMemeory2();
&&& printf("str2
= %s\n", str2);
执行结果:test1程序报错,test2打印乱码或者“Hello world”(一般乱码)
结果分析:
在函数中给指针分配空间,实际上是给指针的临时变量分配空间,函数结束后,这个临时变量也消亡,而str仍然为NULL,没有为其分配空间,此时strcpy()是肯定会出错的。
1、可能是乱码,也有可能是正常输出,因为GetMemory返回的是指向“栈内存”的指针,该指针的地址
不是NULL,但其原来的内容已经被清除,新内容不可知,程序员面试宝典里有专门讲该部分知识的。
2、因为p的生命周期在GetMemory函数执行完了就被销毁了,str
指向的是个野指针。&&&&&&&
//相关分析资料摘录
1、指针参数是如何传递内存的?
  如果函数的参数是一个指针,不要指望用该指针去申请动态内存。以下Test函数的语句GetMemory(str, 200)并没有使str获得期望的内存,str依旧是NULL,为什么?
void GetMemory(char *p, int num)
 p = (char
*)malloc(sizeof(char) * num);
void Test(void)
 char *str =
 GetMemory(str, 100); //
str 仍然为 NULL
 strcpy(str, "hello");
// 运行错误
试图用指针参数申请动态内存
  毛病出在函数GetMemory中。编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p =
p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把 _p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西。事实上,每执行一次GetMemory就会泄露一块内存,因为没有用free释放内存。  如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,见示例1.2。
void GetMemory2(char **p, int num)
 *p = (char
*)malloc(sizeof(char) * num);
void Test2(void)
 char *str =
 GetMemory2(&str, 100); // 注意参数是
&str,而不是str
 strcpy(str,
 cout&& str
 free(str);
示例1.2用指向指针的指针申请动态内存
  由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。这种方法更加简单,见示例1.3。
char *GetMemory3(int num)
 char *p = (char
*)malloc(sizeof(char) * num);
void Test3(void)
 char *str =
GetMemory3(100);
 strcpy(str,
 cout&& str
 free(str);
用函数返回值来传递动态内存
  用函数返回值来传递动态内存这种方法虽然好用,但是常常有人把return语句用错了。这里强调不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡,见示例1.4。
char *GetString(void)
 char p[] = "hello
编译器将提出警告
void Test4(void)
 char *str =
 str = GetString(); //
str 的内容是垃圾
 cout&& str
return语句返回指向“栈内存”的指针
  用调试器逐步跟踪Test4,发现执行str = GetString语句后str不再是NULL指针,但是str的内容不是“hello world”而是垃圾。如果把示例1.4改写成示例1.5,会怎么样?
char *GetString2(void)
 char *p = "hello
void Test5(void)
 char *str =
GetString2();
 cout&& str
return语句返回常量字符串
  函数Test5运行虽然不会出错,但是函数GetString2的设计概念却是错误的。因为GetString2内的“hello world”是常量字符串,位于静态存储区,它在程序生命期内恒定不变。无论什么时候调用GetString2,它返回的始终是同一个“只读”的内存块。
  2、杜绝“野指针”
  “野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。 “野指针”的成因主要有两种:
  (1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。例如
char *p = NULL;
char *str = (char *) malloc(100);
(2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。
  (3)指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:
  void Func(void){ cout
&& “Func of class A” &&
void Test(void)
  p = &a;
 p-&Func(); //
p是“野指针”
函数Test在执行语句p-&Func()时,对象a已经消失,而p是指向a的,所以p就成了“野指针”。但奇怪的是我运行这个程序时居然没有出错,这可能与编译器有关。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 c语言数组内存分配 的文章

 

随机推荐