指针是C语言中最难掌握的内容,因此小雅将放慢进程,让大家真正明白指针。
『&』符号是取变量的地址,『*』符号是取地址的内容(即:值)。两个操作正好相反。例如:“&i”就是取变量i的地址,“*(&i)”就是取“&i”这个地址的值,其实就是变量i。即然如此,为什么还要定义指针呢?原来,用『&』所取到的地址,自身只能用而不能修改。因此,直接把『&』取到的地址放到指针变量中去,既然指针变量也是变量,这个变量就可以任意存放其它地址。
#include
<stdio.h>int
main(void
) {int
i = 100, j=200;int
*p; p = &i; //变量i的地址赋给p printf("&i=%p *(&i)=%d\n", &i, *(&i)); printf(" p=%p *p =%d\n\n", p, *p); p = &j; //变量j的地址赋给p printf("&j=%p *(&j)=%d\n", &j, *(&j)); printf(" p=%p *p =%d\n", p, *p);return
0; }
上例中p是指针变量,*p是p的指针,p存放的是某个变量的地址,*p存放的是某个变量的值。当*p的内容改变时,p所指的变量的内容也发生改变,因为是同一个地址的存贮单元的值发生改变。同理,当p所指的变量的值发生改变时,*p的内容也随之改变。
#include
<stdio.h>int
main(void
) {int
i = 100, j=200;int
*p; p = &i; //变量i的地址赋给p *p = 500; //将500赋给p指针 //变量i的内容也随之改变为500 printf("&i=%p *(&i)=%d\n", &i, *(&i)); printf(" p=%p *p =%d\n\n", p, *p); p = &j; //变量j的地址赋给p j++; //将p指针的内容+1 //指针*p的内容也随之改变201 printf("&j=%p *(&j)=%d\n", &j, *(&j)); printf(" p=%p *p =%d\n", p, *p);return
0; }
上面2例,指针变量都是用的p,初学者不要认为只能用p,既然是变量,只要不违反命名规则都可以。当指针变量被定义时立即赋值,这时被赋值的是指针变量还是指针呢?下面这段程序请大家千万注意!
#include
<stdio.h>int
main(void
) {char
str[] = "http://www.quanxue.cn/";char
*ptr = "http://www.51minge.com/";char
*point; point = str; //将str数组的地址赋给指针变量point point[11] = 'Q', point[15] = 'X'; printf("str=%s\n",str); ptr[13] = 'M', ptr[16] = 'G'; //这句是错误的,删除后结果如下 printf("ptr=%s\n",ptr);return
0; }
char
str[] = "http://www.quanxue.cn/";中str是数组变量,当地址赋给point之后,point[11]就是str[11],所以其内容可以改变。
char
*ptr = "http://www.51minge.com/";中赋值的性质和上面的str不同。这并不是将"http://www.51minge.com/"赋给*ptr指针,而是先定义一个常量"http://www.51minge.com/",这个常量是定义在“栈”里面,然后将这个常量的地址赋给ptr,而不是*ptr。常量是不能被修改的,因此ptr[13]也就出错了。这是初学者经常犯的错误。
int
i = 129;int
num[] = {50, 25, 75, 100};int
*pt1 = 125; //错误1: 125作为地址赋给pt1, 这段内存是OS用的int
*pt2 = i ; //错误2: 129作为地址赋给pt2, 这段内存是OS用的int
*pt3 = &i; //正确: 变量i的地址赋给pt3, 因为i是基本类型,所以要加&符号int
*pt4 = num; //正确: 数组num的地址赋给pt4,因为num是数组,变量名就代表地址char
*pt5 ; *pt5 = "ABCDE"; //错误3: "ABCDE"是字符串,也是数组, 此处更是常量 pt5 = "ABCDE"; //正确: 赋值时赋的是地址,因此只能赋给指针变量pt5int
*pt6 ; pt6 = i; //错误4: 129作为地址赋给pt6, 这段内存是OS用的 *pt6 = i; //错误5: 129赋给指针pt6,但pt6尚未分配地址,没有空间存放i的值
未赋值的指针变量是不能被使用的,其地址指向未不能使用的空间。建议定义时如果暂不使用,先赋NULL。为一个指针申请空间时,一定义要判断其是否为空,因为分配内存失败时返回NULL。不仅如此,甚至在使用指针时都应该判断一下是否为空。下面讲到的内存分配是重要内容,在下下章详细介绍。
#include
<stdio.h>#include
<stdlib.h>int
main(void
) {char
*pchar; //下面这句出错,忽略之后继续 printf("pchar=%p\n", pchar); //未分配的指针不可用 pchar = NULL; printf("pchar=%p\n\n", pchar); //空指针可用于表达式中 //pchar为空时,动态分配内存if
(!pchar) { pchar = (char
*)malloc(20); //动态分配内存if
(!pchar) { //初学者不要忘记, 这是必要的判断 printf("内存分配失败。"); exit(-1); //退出 } gets(pchar); printf(" pchar=%p\n*pchar=%s\n", pchar, pchar); free(pchar); //内存释放后,指针变量的地址不变if
(pchar) { //pchar并不为空 printf("\n pchar=%p\n*pchar=%s\n", pchar, pchar); //pchar成了“野指针” } }return
0; }