C语言深入学习之指针

一、指针是什么?
C语言里,变量都是存放在内存里,而内存其实就是一组有序字节组成的数组,每个字节都有唯一的内存地址。CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位。这里,数据对象是指存储在内存中的一个指定数据类型的数值或字符串,它们都有一个自己的地址,而指针便是保存这个地址的变量。也就是说:指针是一种保存变量地址的变量。相当于指针是一种货物标签,或者目录索引,只要根据指针我们就可以进行相应的操作,比直接操作内容更快捷。
样式
上图可见,0X00000000等就是指针。内存其实就是一组有序字节组成的数组,数组中,每个字节大大小固定,都是 8bit。对这些连续的字节从 0 开始进行编号,每个字节都有唯一的一个编号。就是指针。
二、指针的三大用处
(一)复杂的数据结构往往需要使用指针来构建,如链表、二叉树等;
(二)C语言是传值调用,而有些操作传值调用是无法完成的,如通过被调函数修改调用函数的对象,但是这种操作可以由指针来完成;
(三)指针的使用使得不同区域的代码可以共享内存数据,访问速度提升了。
三、指针的使用
(一)创建指针
//1、 声明一个 int 类型的指针 p1,一个char类型的指针p2
int *p1;
char p2;
和常规创建变量的唯一区别是加了

//2、创建一个指针数组
int arr[10];
不难理解,就是创建一个10个元素的数组,每个元素都是一个int指针,相当于数组的每一个数据均加个一个指针
//3、创建一个数组指针
int (arr)[10];
这个可以理解为只有一个指针,指向数组,相当于在数组第一个数据位置加了标签
//4、创建一个指向指针的指针

int **p;
个代表了在创建指针的时候,也可以把这个指针当做一种数据,再创建指向这个指针的一个指针,有点像建立一个目录索引,索引的结构是找到另外一个索引,可以理解为两层嵌套的关系。
以上四种类型是行规形式,但基本涵盖了最重要的几种类型。
(二)使用指针
1、两种赋值方式

当int a=10;
第一种:int p=&a;
第二种:int p;
p=&a;

这两种的实现结果是一样的。输出的两种结果
printf("%d\n", p);//输出的P1的内容

printf("%#X\n", p);
//输出的P1的地址
2、设置空指针
NULL 的指针是一个特殊的指针变量,表示不指向任何东西。可以通过给一个指针赋一个零值来生成一个 NULL 指针。
示例:
int *p = NULL;
printf(“p的地址为%d\n”,p);
这两句输出的为0.
(三)指针运算
示例1:

int a[10] = {1,2,3,4,5,6,7,10,9,1};
int sub;
int *p1 = &a[2];
int *p2 = &a[8];
sub = p2-p1;
printf("%d\n",sub);
*这段的输出结果是6,代表两个指针之间的距离是6.
示例2:
当执行 p1++;后
再执行printf("%d\n",*p1);结果为4;
当再执行 p1++;后
再执行printf("%d\n",*p1);结果为5;
说明指针可以自动加1下移,当然也可以–上移。也可以+N,移动N个位置。
*(四)指针参与数组操作
int x[10] = {1,2,3,4,5,6,7,8,9,0};
int p = x;
printf(“x的地址为:%p\n”,x);
printf(“x[0]的地址为:%p\n”,&x[0]);//这个和上一个显示的都是地址一样
printf(“p的地址为:%p\n”,&p); //这个显示指针的地址
printf(“p的值为:%d,X[0]的值为:%d\n”,p,x[0]); //这个都显示1
p += 2;

printf("
(p+2)的值为:%d\n",*p);//这个显示3
(五)数组指针操作
int arr[2][3] = {1,2,3,4,5,6};
int (*p)[3];
p = arr;
for(int i=0; i<2;i++)
for(int j=0; j<3;j++)
printf("%d “,arr[i][j]); //输出的是1 2 3 4 5 6
printf(”\n");
printf("%d\n",(*p)[0]);//输出1
printf("%d\n",(*p)[1]);//输出2
printf("%d\n",(*p)[2]);//输出3
p++;
printf("%d\n",(*p)[0]);//输出4
printf("%d\n",(*p)[1]);//输出5
printf("%d\n",(*p)[2]);//输出6
(六)指针的指针
以下代码在测试输出时,可以看到显示的内容都是一样的。
int i = 10;
int *p = &i;
int **q = &p;
int ***r = &q;
printf(“i = %d\n”, i);
printf(“i = %d\n”, *p);
printf(“i = %d\n”, **q);
printf(“i = %d\n”, ***r);
通过以上代码体会指针的指针,也就是将指针作为内容再嵌套指针,相当于一批货物,每个货物有一个标签,而仓库管理员在标签基础上又做了一套查找标签的索引目录。
当然,更上一层也可以根据现行的索引目录再做一层索引目录的索引,以此类推。但在实际应用中,一般用到指针的指针这第二个层级基本够用了。
(七)指针用来操作结构体的方式

# include <stdio.h>
# include <string.h>
struct AGE
{
    int year;
    int month;
    int day;
};
struct SelfMsG
{
    char name[20];  //姓名
    int num;  //编号
    struct AGE birthday;  //生日
    float score;  //考试成绩
};
int main(void)
{
    struct SelfMsG selfmsg1; /*用struct STUDENT结构体类型定义结构体变量student1*/
    struct SelfMsG *p=&selfmsg1;  /*p指向结构体变量student1的首地址, 即第一个成员的地址*/
    strcpy((*p).name, "小强");  //(*p).name等价于student1.name
    (*p).birthday.year = 1991;
    (*p).birthday.month = 10;
    (*p).birthday.day = 29;
    (*p).num = 1207041;
    (*p).score = 100;
    printf("name : %s\n", (*p).name);  //(*p).name不能写成p
    printf("birthday : %d-%d-%d\n", (*p).birthday.year, (*p).birthday.month, (*p).birthday.day);
    printf("num : %d\n", (*p).num);
    printf("score : %.1f\n", (*p).score);
    return 0;
}

以上这种方式,实际就是将指针和实例化结构体直接视为一类东西来使用。当然,C语言也提供了一种替代性方式来操作,即->,总的来说包括以下三 种形式是实现的相同功能:
结构体变量.成员名。
(*指针变量).成员名。
指针变量->成员名。
从实际操作来看,大部分程序员写代码,习惯使用方式1或3,个人推荐方式3。
(八)函数指针和指针函数
1、函数指针

# include <stdio.h>
# include <string.h>
int add(int x,int y){
    return x+y;
}
int sub(int x,int y){
    return x-y;
}
//函数指针
int (*fun)(int x,int y);
int main(void)
{
    fun=add;
    printf("%d\n",(*fun)(3,4));   //结果是7
    fun=&sub;
    printf("%d\n",fun(5,7));    //结果是-2
    return 0;
}

总体来看,这种模式我还没觉得有太多用处,了解即可。
2、指针函数

#include<stdio.h>
typedef struct Data{
    int a;
    int b;
}Data;
//指针函数
Data* f(int a,int b){
    Data * data;
    data->a = a+1;
    data->b = b+2;
    return data;
}
int main()
{
    Data *li;
    li=f(4,5);
    printf("%d\n%d\n",li->a,li->b);//运算结果是5,7
    return 0;
}

指针函数实际上就是可以实现定义一个函数,当需要在主程序操作时,通过指针形式加了一个标签,把函数通过指针进行操作更加便捷了。同时,在main中,将Data结构体实例化,在使用时这种方式逻辑上相对复杂,需要大家慢慢悟,我也是在不断学习中,环境一起交流。。。

发布了11 篇原创文章 · 获赞 16 · 访问量 2091

猜你喜欢

转载自blog.csdn.net/qxrobot/article/details/103689010
今日推荐