赞
踩
目录
从根本上看,指针(pointer)是一个值为内存地址的变量(或数据对象)。比如char类型变量的值为字符,int 类型变量的值是整数,指针变量的值是地址。例如:
int * p;//定义了一个指针变量p,p的类型为int *,p指向的地址为 int 类型
通俗来讲,指针就是地址,地址就是指针,不过要注意的是,虽然我们在平时会将指针变量简称为指针,但指针变量和指针是有所不同的,指针变量是存放地址的变量,也就是存放指针的变量。
1) * (星号)
C语言中*可以表示乘号,也可以表示指针符号。这两个用法是毫无关联的,只是恰好用了同一个符号而已,星号在用于指针时有两种用法:
①指针定义时,*结合前面的类型用于表明要定义的指针的类型;
②指针解引用,解引用时*p表示p指向的变量本身。
- int *p;//这是星号的第一种用法,定义了一个指针变量 P
- int *q ,*r;//当同时想定义两个或者多个指针时,也可以采用这样的语句
- int i=5,j;
- p = &i; //p保存了i的地址,p指向i
- j = *p;//这是星号的第二种用法,把p指向的地址上的值赋给j,此时j=5
2) & (取地址符)
取地址符使用时直接加在一个变量的前面,然后取地址符和变量加起来构成一个新的符号,这个符号表示这个变量的地址。
指针初始化目的就是让指针知道指向那个地址。共有两种方式初始化指针:①在声明指针时便告诉指针指向地址;②不在声明指针的时候初始化,而是把地址直接赋值给指针变量。
注意:不可以在指针不清楚指向地址的情况下给指针赋值(但是char p=0或者p=NULL除外,该语句表示指针为空)。
①在声明指针时便告诉指针指向地址
- #include <stdio.h>
- int main (void)
- {
- int i=5;
- int *p=&i;
- return 0;
- }
②不在声明指针的时候初始化,而是把地址直接赋值给指针变量
- #include <stdio.h>
- int main (void)
- {
- int i=5;
- int *p;
- p = &i;
- return 0;
- }
③不可以在指针不清楚指向地址的情况下给指针赋值(错误)
- #include <stdio.h>
- int main (void)
- {
- int i=5;
- int *p;
- *p = 5;
- return 0;
- }
- int * p;
- int i=5,j;
- p = &i;//一个指针变量指向某个普通变量,则*指针变量等同于普通变量
- //对于此处即:*p=i=5 在所有出现 *p 或 i 的位置,两者可相互替换
- j = *p;//通过这几步,就可以将 i 的值 5 赋给 j
1)内存泄漏
指针指向一个地址,也就是一个空间,如果只给指针分配空间,而未释放掉分配的空间,就会导致内存泄漏,导致内存越用越少;但如果,有多个指针同时指向同一个空间,而进行多次内存释放,就会使程序崩溃,导致无法运行。
2)空指针NULL
空指针就是值为0的内存逻辑地址,当对逻辑地址0(NULL)所代表的内存进行读写操作时,程序就会崩溃。(返回值为指针的函数通常使用空指针作为失败时的返回值)
3)野指针
指向的位置不可知的指针。
出现原因:①声明指针后并未初始化
②变量内存释放后,指针变量还保存着该变量的内存地址
一维数组名,是一个指针常量,他存放的是数组第一个元素的地址,例如:
- #include <stdio.h>
- int main (void)
- {
- int a[5];
-
- printf ("%d\n",&a[0]);//此处输出为a[0]的地址
- printf ("%d\n",a);//此处输出为数组名a的含义
-
- return 0;
- }
若两者输出结果相同,则说明一维数组名存放的是数组第一个元素的地址,运行程序输出结果如下:
显然,两者输出结果相同,那么说明一维数组名存放的是数组第一个元素的地址。
指针和下标总存在着这样一个关系:如果 p 是一个指针变量,则 p[i] 永远等价于 *(p+i)
- # include <stdio.h>
- int main(void)
- {
- int a[5] = { 1,2,3,4,5};
- int i;
-
- for( i = 0 ; i < 5 ; i++ )
- {
- printf("%d " , a[i]);
- }
- printf ("\n");
-
- for(i = 0 ; i < 5 ; i++ )
- {
- printf("%d " , *(a+i));
- }
-
- return 0 ;
- }
运行程序,输出结果如下:
由此便可以证明该关系,p[i] 等价于 *(p+i)
注意区分:
int (*p[10])的含义是定义了一个数组,数组名为p,其中包含10个指针,指针指向整型类型数据
int (*p)[10]的含义是定义了一个指针,指针指向一个数组,数组中有10个元素,元素类型为整型
如果一个指针指向的是另一个指针,我们就成他为二级指针,或者指向指针的指针。
那么如果指针指向的是一个二级指针,我们就称他为三级指针.......
那么对于多级指针,我们又该如何操作呢?
- #include <stdio.h>
- int main (void)
- {
- int i=10;
- int *p = &i;//定义了一个一级指针, p 存放 i 的地址
- int **q = &p;//定义了一个二级指针,q 存放 p 的地址
- int ***r = &q;//定义了一个三级指针,r 存放 q 的地址 r是int ***类型,所以r只能存放int **类型变量的地址
-
- //r = &p;//这样写是错误的 r是int ***类型,所以r只能存放int **类型变量的地址 不能存放int *类型变量的地址
-
- printf ("%d\n",i);
- printf ("%d\n",*p);
- printf ("%d\n",**q);
- printf ("%d\n",***r);
-
- return 0;
- }
- /*
- ----------------
- 输出结果:10
- 10
- 10
- 10
- ----------------
- */
i p q r 之间的关系可通过下图来理解
指针变量不能相加 不能相乘 不能相除
如果两个指针变量指向同一块连续空间中不同的储存单元,则这两个指针变量可以相减。
- int i=5;
- int j=10;
- int *p = &i;
- int *q = &j;
此时 p-q 并没有实际意义,若将 p 和 q 放入同一个数组中,p-q 才会有实际意义。
- #include <stdio.h>
- int main (void)
- {
- int a[5];
- int *p, *q;
-
- p = &a[1];
- q = &a[4];
-
- printf ("p和q所指向的单元相隔%d个单元\n",q-p);
-
- return 0;
- }
运行结果如下:
以上就是初次学习和了解指针后,我的理解和思考。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。