【Linux C】浅谈指针(一)

来源:互联网 发布:台湾娱乐圈知乎 编辑:程序博客网 时间:2024/06/05 02:12

一、指针是什么?


  指针是变量。


  首先我们来明确变量的三大特点

  ①变量的数据类型:主要说明变量占用内存空间大小,如int型。

  ②变量的作用域:变量的有效性的范围,即:变量的使用范围。

  ③变量的存储类型:变量在内存中的存储方式。不同的存储方式影响变量在内存中的生存周期。

 

  我们应该正确理解指针,即指针是变量。这样指针便有了变量的特性:

  ·系统为指针分配内存空间

  ·指针有自己的地址

  ·指针能够存值,但这个值比较特殊——地址


  简单来说就是:指针是一个变量,这个变量里保存的都是地址

 

二、指针的类型和指针所指向的类型


用以下声明为例:

int *p;char *p;int **p;int (*p)[3];int *(*p)[4];

1.指针的类型

  可以把指针声明语句里的指针的名字去掉,剩下的部分就是这个指针的类型,这也是指针本身所具有的类型。

int *p;  //指针的类型是int*char *p;  //指针的类型是char*int **p;  //指针的类型是int**int (*p)[3];  //指针的类型是int(*)[3]int *(*p)[4];  //指针的类型是int*(*)[4]

 2.指针所指向的类型

  当我们通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那一片内存区里的内容当做什么来看待。

  可以把指针声明语句中的指针名字和名字左边的“*”去掉,剩下的就是指针所指向的类型。

int *p;  //指针所指向的类型是intchar *p;  //指针所指向的类型是charint **p;  //指针所指向的类型是int*int (*p)[3];  //指针所指向的类型是int()[3]int *(*p)[4];  //指针所指向的类型是int*()[4]

 

三、指针本身所占据的内存区


  指针本身占了多大的内存空间?我们来测试一下:

#include <stdio.h>int main(){    printf("len = %d\n",sizeof(int *));    return 0;}


运行结果:

len = 4

  可以看到,整型指针占了4字节,那么其他类型的指针呢?我们来测试一下:

#include <stdio.h>int main(){    printf("len = %d\n",sizeof(char *));    printf("len = %d\n",sizeof(short *));    printf("len = %d\n",sizeof(int *));    printf("len = %d\n",sizeof(long *));    printf("len = %d\n",sizeof(float *));    printf("len = %d\n",sizeof(double *));    printf("len = %d\n",sizeof(long long *));    return 0;}


运行结果:

len = 4len = 4len = 4len = 4len = 4len = 4len = 4

  由此我们可以得出一个结论——指针的长度时固定的,任何类型的指针都是4字节。


  原因:所有的指针都用来保存地址,而在操作系统中,地址的长度是固定的,因为地址的长度是由操作系统的位数决定的。32位的操作系统中是4字节,64位的操作系统中是8字节。

 

四、指针的两个运算符“*”和“&”


  接下来就来谈谈我们今天想要说的指针的两个运算符“*”和“&”。


  “&”运算符:取地址运算符,&p即是变量p在内存中的实际地址

  “*”运算符:通常称为间接引用运算符,它返回指针所指向的对象的值。


  简单来说,“*”是取内容,“&”是取地址。


1、int num = 5;

  在这里我们定义了一个整型变量num,并赋值为5。首先,在我们定义num为int型时,系统为num分配了4个字节的空间,每个字节都有地址,分别为0x1000,0x1001,0x1002,0x1003,而“&num”就相当于0x1000,即拿首字节的地址作为整体的地址。


  地址是有划分的,原因是它的步长是不一样的。


  红色的地址代表整体的地址,一个整型指针加1,即跳过了一个整数,也就是跳过个了4个字节。

 

2、“指向的内存空间”和“对应的内存空间”

int num = 5;  int *p = &num;

  我们来分析一下“int *p = &num;”的含义:先给p分配4字节空间,把num的地址取出来,存放在给p的4个字节空间里。

由上图得出以下分析:

num++;  //5变成6,即对num对应的内存空间的值加1p++;  //0x1000变成0x1004,即对p对应的内存空间的值加1,同时还要考虑到步长(*p)++;  //5变成6,*p是对p指向的内存空间操作


  *p:根据p对应的内存空间里保存的地址找到其对应的内存空间,即对p指向的内存空间操作。


  即在上图中,有:“p == &num”    “*p == num == *(&num)”。


再如下图所示:

int num = 5;int *p = #int **pp = &p;  //指针变量,4个字节


有如下分析:

p++;  //0x1000变成0x1004(*pp)++;  //0x1000变成0x1004pp++;  //0x2000变成0x2004(**pp)++;  //5变成6


  在上图中,有:“num == *p == **pp == *(&num)”,“&num == p == *pp”


  如果在上图的基础上再加上“int ***ppp = &pp;”呢?(**ppp)++;产生的现象是0x1000变成0x1004。这时有:

  num == *p == **pp == ***ppp == *(&num),&num == p == *pp == **ppp。

  

  *p操作的是 p指向的空间

  p操作的是 p对应的空间


  一维指针保存基本变量的地址,二维指针保存一维指针变量的地址,三维指针保存二维指针变量的地址。


  顺便提一句,超过二维的指针为远指针


0 0
原创粉丝点击