5.2 指针的一般性用法及注意事项

在学习指针的一般性用法时,读者首先要清楚地知道指针是地址,而这个地址的特殊性在于指向的是一片连续内存区域的起始地址。下面通过代码来看指针的一般性用法及注意事项。


include<stdio.h>

void main()

{

int a,b;

intpa,pb;

a=100;

b=200;

pa=&a;

pb=&b;

printf("——————————变换前—————————-\n");

printf("a=%d\tb=%d\n",a,b);

printf("pa=%d\tpb=%d\n",pa,pb);

*pa=300;

int c=500;

pb=&c;

printf("——————————变换后—————————-\n");

printf("a=%d\tpa=%d\n",a,pa);

printf("c=%d\tb=%d\tpb=%d\n",c,b,pb);

return;

}


运行结果:


——————————变换前—————————-

a=100 b=200

pa=100pb=200

——————————变换后—————————-

a=300*pa=300

c=500 b=200*pb=500


上面的代码可以通过图5-4来展示变换前后各变量的值。在一开始时定义了两个整型变量a和b,然后定义了两个整型指针,分别指向变量a和b的内存单元。所以接下来直接打印出的a和b与采用pa和pb打印出来的结果完全一样。但是,在接下来的代码中通过“pa=300;”来对pa所指向的内存单元进行赋值,而pa所指向的内存单元也就是变量a所指向的内存单元,所以在接下来打印出的a的值不再是初始值了,而是后来对pa赋的值。定义了一个整型变量c,然后将pb指向c在内存中的存储单元,而不是变量b在内存中的存储单元,所以接下来输出的变量b的值仍是之前对b的赋值,而指针pb所指向的内存单元的值变为此时它所指向的变量c在内存单元中的值。

5.2 指针的一般性用法及注意事项 - 图1

图 5-4 变换前后的内存结构图

读者要注意上面的代码中的“*pa=300;”,在这里可以使用这句代码的原因是在此之前通过pa=&a使pa指向变量a在内存中的存储单元。如果定义了一个指针并直接使用,会发生什么现象呢?看看下面的代码。


include<stdio.h>

void main()

{

int*pa;

*pa=10;

return;

}


在上面的代码中简简单单地定义了一个整型指针变量pa,然后直接对其进行赋值操作,编译的时候没有发现任何错误,但是运行程序时发现程序直接崩溃了。为什么会出现这样的现象呢?这是因为一开始定义的指针变量指向的是一个“不可用”的内存,不能够对其进行赋值操作,所以在使用的时候要尤其注意那些没有初始化的指针。对于那些不使用的指针,读者要养成将其赋值为NULL的习惯。现在将上面的代码修改如下:


include<stdio.h>

include<stdlib.h>

void main()

{

intpa=(int)malloc(sizeof(int)*4);

int i;

for(i=0;i<4;i++)

{

*(pa+i)=i+1;

printf("(pa+%d)=%d\n",i,(pa+i));

}

free(pa);

return;

}


运行结果:


*(pa+0)=1

*(pa+1)=2

*(pa+2)=3

*(pa+3)=4


在上面的代码中,通过malloc()函数为int型指针pa分配了内存,使得pa在内存中有了固定的存储区域,所以在接下来的代码中可以对其进行赋值。值得注意的是,pa使用时占用的内存空间不要超过所分配的内存大小。最后使用了一个free()函数来释放申请的内存空间,接下来,如果想要再次使用pa指针,该怎么办呢?很多人可能想到了使用if语句来判断当前pa指针是否可用,相应的代码如下:


include<stdio.h>

include<stdlib.h>

void main()

{

intpa=(int)malloc(sizeof(int)*9);

int i;

for(i=0;i<9;i++)

{

*(pa+i)=rand()%100;

printf("(pa+%d)=%d\t",i,(pa+i));

if((i+1)%3==0)

printf("\n");

}

free(pa);

int a=12;

if(pa!=NULL)

{

pa=&a;

printf("%d\n",*pa);

}

return;

}


运行结果:


(pa+0)=41(pa+1)=67*(pa+2)=34

(pa+3)=0(pa+4)=69*(pa+5)=24

(pa+6)=78(pa+7)=58*(pa+8)=62

12


在上面的代码中,在使用free()函数释放掉pa所指向的内存单元之后,接下来使用if语句判断当前的pa是否为空。从运行结果可以发现,虽然使用free()函数释放了pa所指向的内存单元,但是pa的值并不为NULL,而是打印输出了12。使用free()函数前后,pa指针究竟有什么变化呢?看看下面的代码。


include<stdio.h>

include<stdlib.h>

void main()

{

intpa=(int)malloc(sizeof(int));

*pa=726;

printf("pa=%d\n",pa);

printf("使用free()函数之前pa=%d\n",pa);

free(pa);

printf("使用free()函数之后pa=%d\n",pa);

return;

}


运行结果:


*pa=726

使用free()函数之前pa=3681952

使用free()函数之后pa=3681952


从上面的运行结果发现,在使用free()函数前后,指针变量pa所指向的内存单元的地址并没有发生变化,所以在前面的代码中不能通过if语句来判断是否对pa使用了free()函数,而要人为指定pa的值。因此我们要养成将那些使用了free()函数的指针赋值为NULL的习惯,这样还能够很好地防止使用完free()函数之后再次使用free()函数而导致程序崩溃的情况出现,如:


include<stdio.h>

include<stdlib.h>

void main()

{

intpa=(int)malloc(sizeof(int));

*pa=726;

printf("使用free()函数之前pa=%d\n",pa);

free(pa);

printf("使用free()函数之后pa=%d\n",pa);

pa=NULL;

free(pa);

free(pa);

return;

}


运行结果:


使用free()函数之前*pa=726

使用free()函数之后*pa=-572662307


由上面的运行结果可以看出,在使用完free()函数之后,变量pa所指向的内存单元中的数据变为“垃圾数据”,不再是之前保存的数据。同时,在使用了free()函数之后将pa指针的值设置为NULL,之后又两次对pa使用了free()函数,这时程序并没有因此而崩溃,所以在指针的操作中,要养成将那些不再使用了的指针赋值为NULL的习惯,避免由于粗心带来的错误。