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-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的习惯,避免由于粗心带来的错误。