从指向指针的指针说起

来源:互联网 发布:ks线切割编程软件 编辑:程序博客网 时间:2024/06/15 06:13

这是我第一篇博文,我从一周前就开始想要写什么。曾经想过直接上MFC各个控件的普通用法,也曾经想从我刚开始学的驱动说起。可是到现在,因为我上次编写的一个程序让我改变了想法。程序要求是这样的:需要一个结构体里面存放电脑上U盘设备的信息,大致有U盘个数、每一个U盘的盘符、每一个U盘的出厂ID号。结构体如下:

我遇到的问题就是UID的问题,当时的想法是用一指针数组存放每一个U盘的ID,到使用时就直接用p->arrDiskID[i]就可以了。但是问题来了——指针的释放。我的思路是这样的:

先由Create函数将测试数据拷贝到指针指向的数组中,数组的大小按照测试数据的大小分配。在释放的时候用delete释放各个指针再将指向指针的指针释放代码如下:

当时在释放的时候不知道怎么样释放指向数据数组的指针查找了一些资料才有了上面的代码。而写到这里并不是我想说的,从这里我想到了一些指针的相关知识,现在也一起记下以备后用。

1 内存的分配问题

内存分配方式有三种:

(1)   从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

(2)   在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

(3)   从堆上分配,亦称动态内存分配。程序在运行的时候用mallocnew申请任意多少的内存,程序员自己负责在何时用freedelete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

知道了内存分配的三种方式,在具体实践中在最后两种很容易犯错,在这里我引用一篇牛人写的文章为引:

void GetMemory(char *p)

{

p = (char *)malloc(100);

}

void Test(void)

{

char *str = NULL;

GetMemory(str);  

strcpy(str, "hello world");

printf(str);

}

此程序运行结果就是程序崩溃,因为GetMemory并不能传递动态内存,Test函数中的 str一直都是 NULLstrcpy(str, "hello world");将使程序崩溃。

char *GetMemory(void)

{  

char p[] = "hello world";

return p;

}

void Test(void)

{

char *str = NULL;

str = GetMemory();   

printf(str);

}

 

可能是乱码。因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知。

void GetMemory2(char **p, int num)

{

*p = (char *)malloc(num);

}

void Test(void)

{

char *str = NULL;

GetMemory(&str, 100);

strcpy(str, "hello");  

printf(str);   

}

1)能够输出hello

2)内存泄漏

void Test(void)

{

char *str = (char *) malloc(100);

    strcpy(str, “hello”);

    free(str);     

    if(str != NULL)

    {

      strcpy(str, “world”);  

printf(str);

}

}

篡改动态内存区的内容,后果难以预料,非常危险。因为free(str);之后,str成为野指针,if(str != NULL)语句不起作用。这个结果告诉我们在释放delet/free后应该直接把指针指向NULL不然指针便成为野指针,而且在每次使用指针前应先判断指针是否为NULL

从这里又开始了我们的第二个问题:

2 内存释放

这个问题对于栈内存来说我们不用关心,因为程序会自动释放。而对于分配在堆上的内存就必须要关心了。

指针释放的时候一般我们都用delete p或者delete []p ,这两者的区别是显而易见的:前者只是释放了p指向的单一地址,相当于释放了p[0],p以后的内存空间就泄露了,使用后者就可以完全释放。而用malloc/free 就没有这样的情况。

对于指向指针的指针这样的情况我们使用WCHAR** p = new PWCHAR[n];p[0] = new WCHAR[n2];这样的方式来分配了内存。使用delete []*p(=delete []p[0])…来一个个释放内存,这里要说明的是使用delete []*p也只是相当于释放了p[0],以后分配的也没有释放。

3 易混淆的几个概念

int *p;     p为指向整型量的指针变量
int *p[n]; 
  p为指针数组,由n个指向整型量的指针元素组成。
int (*p)[n];   p
为指向整型二维数组的指针变量,二维数组的列数为n
int *p() 
   p为返回指针值的函数,该指针指向整型量
int (*p)() 
  p为指向函数的指针,该函数返回整型量
int **p 
    p为一个指向另一指针的指针变量,该指针指向一个整型量。
例子:

static int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
int(*p)[4];
int i,j;
p=a;
for(i=0;i<3;i++)
for(j=0;j<4;j++) 
printf("%2d ",*(*(p+i)+j));

    ps.谨以此篇送给Grace你是我生命中遇到过最美丽的阳光。

 

 

 

原创粉丝点击