关于指针的一些基本常识

这两天因为工作需要,很是纠缠于C++中的指针(严格意义上来说应该算是C),虽然已经不算是初学者了,但是因为很长时间没有使用,还是有很多混淆的地方,所以干脆在此做一个总结。

首先定义一个最简单的int指针:

1 #include <iostream>
2 using namespace std;
3 
4 int main(void)
5 {
6     int *single_pointer;
7     cout<<single_pointer;
8     cout<<*single_pointer;
9 }

 

可以看到VS2005的输出如下:

究其原因,因为只给出了指针的声明,却没有初始化,因此当执行到cout输出时,会出现访问内存错误的情况。

修改代码:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int main(void)
 5 {
 6     char ch = 'a';
 7     char *pointer_1 = &ch;
 8     printf("%c\n", ch);
 9     printf("%p\n",&ch);
10     printf("%p\n", pointer_1);
11     printf("%p\n",&pointer_1);
12     printf("%c\n",*pointer_1);
13 }

 

输出结果为:

到这里可以很明显的看出:

0x0018FF2B为字符ch的地址,

指针pointer_1指向字符ch的内存地址,所以pointer_1与对字符ch取地址&ch的打印结果是一样的。

而0x0018FF1C则为指针pointer_1本身的值。

或许这样可以看得更清楚:

只要搞清楚,指针本身也是一种数据类型,占用空间大小为四个字节,就很容易理解这一点了。

接着是二维指针,亦即所谓的指针的指针。

话不多,先贴代码:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int main(void)
 5 {
 6     char **pPointer = NULL;
 7     pPointer = (char **)malloc(10 * sizeof(char *));
 8 
 9     *pPointer = "12";
10     *(pPointer + 1) = "345";
11     *(pPointer + 2) = "6789";
12 
13     printf("*pPointer: %s\n\n",*pPointer);
14 
15     printf("P *pPointer: %p\n",*pPointer);
16     printf("P *(pPointer + 1): %p\n",*(pPointer + 1));
17     printf("P *(pPointer + 2): %p\n\n",*(pPointer + 2));
18 
19     printf("& &*pPointer: %p\n",&(*pPointer));
20     printf("& &*(pPointer + 1): %p\n",&*(pPointer + 1));
21     printf("& &*(pPointer + 2): %p\n\n",&*(pPointer + 2));
22 
23     printf("P pPointer: %p\n",pPointer);
24     printf("P pPointer + 1: %p\n",pPointer + 1);
25     printf("P pPointer + 2: %p\n\n",pPointer + 2);
26 
27     printf("& pPointer: %p\n",&pPointer);
28     printf("& pPointer + 1: %p\n",&pPointer + 1);
29     printf("& pPointer + 2: %p\n\n",&pPointer + 2);
30 
31     printf("C **pPointer: %c\n",**pPointer);
32     printf("C **pPointer + 1: %c\n",**pPointer + 1);
33     printf("C **pPointer + 2: %c\n\n",**pPointer + 2);
34 
35     printf("S *pPointer: %s\n",*pPointer);
36     printf("S *pPointer + 1: %s\n",*pPointer + 1);
37     printf("S *pPointer + 2: %s\n\n",*pPointer + 2);
38 
39     printf("S *pPointer: %s\n",*pPointer);
40     printf("S *(pPointer + 1): %s\n",*(pPointer + 1));
41     printf("S *(pPointer + 2): %s\n\n",*(pPointer + 2));
42 
43     printf("& &pPointer: %p\n",&pPointer);
44     printf("& &(*pPointer): %p\n\n",&(*pPointer));
45 
46     printf("D sizeof(*pPointer): %d\n",sizeof(*pPointer));
47     printf("D strlen(*pPointer): %d\n",strlen(*pPointer));
48     printf("D sizeof(**pPpointer): %d\n\n",sizeof(**pPointer));
49 }

VS2005下的输出为:

首先明确一点?何为指针?

看一个最简单的指针的定义:char *p

首先,指针本身是一种数据格式,有别于int这样的基本数据类型,它会指向一块指定的内存(所以指针如果没有初始化会出现野指针的情况)。因此,作为指针数据类型,p本身会在内存中占用一块大小为sizeof(void *)在本文中值则为4的内存,同时因为p被声明为char *而不是void *,所以p所指向的内存中存放的是一个char类型的值,占一个字节。

理解这一段之后再来看所谓二维指针的定义,也就很容易理解了。

来看二维指针的定义:char **p,实际上应该理解为(char *) *p

亦即,p为一个指针,p所指向的内存中存放的数据为另一个指针,而这个p指针所指向的指针指向的最终内存块存放的为一个char值,p->another_pointer->char。

笔者做了一个粗略的描述图:

其中temp_1-3三个指针为笔者虚拟的存在,分别代表指针pPointer,pPointer+1与pPointer+2所指向的内存。

此时再来看上面的输出:

pPointer为指向指针的指针,它在内存中的地址为0X0018FF28,它所指向的内存为&*pPointer,也就是上图中temp_1的位置,为0X00520F60,可以看到由于申请内存的大小为10*sizeof(char *),因此temp_1-3的三块地址是连续在一起的。

而*pPointer本身也是一个指针,它所指向的内存地址为0X00415984,该内存中存放的是一个char型的字符,值为‘1’

最后,对代码中的一些输出做一些解释:

名称 类型 解释
pPointer 指针 指针的指针
*pPointer 指针 pPointer所指向的内存中存放的指针
**pPointer 字符 对指针(*pPointer)做解引用操作所获取的值
&*pPointer 地址 pPointer所指向的内存地址,亦即上文中temp_1指针的地址(区别于指针指向的地址)
pPointer+1 指针 指针pPointer所指向的内存的后一块内存,亦即上文中的temp_2
*pPointer+1 指针 指针*pPointer(亦即temp_1)所指向内存的后一块内存,上文中为字符‘2’所在的内存
posted @ 2015-04-14 16:33  Berne  阅读(819)  评论(0编辑  收藏  举报