C语言指针详述

指针概念:

指针是程序语言中的一种对象,计算机对数据的访问是通过寻址实现的,而指针就能存放数据的地址,使得程序员能够通过对指针变量的操作来实现对数据(或说变量)的操作。

如图:
这里写图片描述

这里 p 是一个指针变量,p 里面存放着变量 a 的地址,那么我们找到 p 就可以对变量 a 进行读写等操作了。


普通指针:

声明格式:数据类型 *指针名;

例如:int *p;
这里就声明了一个整数类型的指针 p
对指针变量赋值通过运算符 & 完成(如:p=&a)
对指针变量所指向的变量进行访问通过 * 完成(如:*p)

#include<stdio.h>
int main()
{
    int a=10;                      //声明一个整形变量
    int *p;                        //声明一个整形的指针变量

    p=&a;                          //将变量 a 的地址传给指针变量 p
    printf("%d\n",p);              //输出 p 存放的内容,即变量 a 的地址
    printf("%d",*p);               //读取 p 所存放地址对应的变量 a  

    return 0;
}

当然对于 char , long , float , double 等类型的数据都可以声明指针变量

普通指针的用途:

1、指向单个变量
2、指向单个数组

int a[10]={0};                    //声明一个整形数组
int *p;                           //声明一个整形指针
p=a;                              //把数组 a 的首地址传给 p 
/*当然最后一行还可以写为 p=&a[0] */

3、指向结构体

struct student{
    int id;
    char name[10];
    int grade;
}

struct student *student1;  //这里就声明了一个 student 这个结构体的指针变量

4、指向函数(笔者将在后面的“指针函数”板块进行讨论)


指针数组:

上面我们介绍了单个的指针,如果我们现在需要多个指针呢,那怎么办?
当然,我们就应该多声明一些指针变量,例如:int *p1,*p2,*p3 … …
读者必想,这样写是不是太麻烦了,有没有简洁点的办法就可以声明多个同类型的指针变量呢?当然有的,那就是指针数组。其实,指针数组就是由多个同类型指针组合而成的数组。

定义形式:数据类型 *p[N];
说明:N为指针数组元素个数

例如:

#include<stdio.h>
int main()
{
    int a=1;                    
    int b=10;
    int c=100;
    int *p[3];                               //定义一个整形指针数组

    p[0]=&a;                                 // 对指针数组元素逐个赋值  
    p[1]=&b;
    p[2]=&c;

    printf("%d\n",p[0]);
    printf("%d\n",p[1]);
    printf("%d\n",p[2]);

    return 0;
}
指针数组的用途

1、指向多个单一的同类型变量
2、指向多个数组

//以指向一个二维数组为例
#include<stdio.h>
int main()
{
    int a[3][4];                     //声明一个二维数组
    int *p[3];                       //声明一个指针数组
    int i;

    for(i=0;i<3;i++)
        p[i]=a[i]
    //将二维数组拆分成3个一维数组,并把每一个一维数组首地址赋值给指针数组的元素
    /*事实上这条语句还有其它写法,例如 p[i]=&a[i][0]*/

    printf("%d\n",p[0]);
    printf("%d\n",p[1]);
    printf("%d\n",p[2]);
    return 0;
}

3、指向多个同类型结构体


数组指针:

数组指针是指向数组地址的指针。

以二维数组为例

定义形式:数据类型 (*p)[N];
说明:这里的括号不可少,N为该数组指针的一维子数组的元素个数(可以省略,看不懂的话看例子)。同时,这里涉及到运算符的优先级(() 和 [] 从左往右结合):() = [] > *

p 是一个指针变量,它指向包含N个所声明数据类型元素的一维数组,此时 p 的增量以它所指向的一维数组长度为单位;
*(p+i) 是二维数组a[i][0]的地址;
(p+i)+j 表示a[i][j]元素的地址,(*(p+i)+j) 表示 a[i][j] 的值。

例如:

#include<stdio.h>
{
    int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};  //声明一个二维数组
    int (*p)[4];                              //声明一个数组指针
    int i;

    p=a;                                      //让数组指针指向该二维数组

    for(i=0;i<3;i++)                          //输出每个一维数组的首地址
        printf("%d\n",*(p+i));

    printf("\n%d\t %d\n",a[2][0],&a[2][0]);
    printf("%d\t %d",*(*(p+2)+0),*(p+2)+0);
    return 0;
}

运行结果:
运行结果


指针函数:

指针函数本身是一个函数,只不过这个函数的返回值为某一类型的指针。

定义形式:返回值类型 *函数名(函数参数列表)
说明:指针函数常用于寻找并返回数组中某个元素的地址。

例如:

#include<stdio.h>

int *Test(int *p,int a);

int main()
{
    int score[3]={100,60,20};

    printf("需寻找的目标值(100),其地址为:%d\n",&score[0]);
    printf("已找到目标值(100),其地址为:%d",Test(score,100));

    return 0;
}

int *Test(int *p,int a)
{
    int i=0;
    while(p[i]!=a)
        i++;
    return &p[i];
}

运行结果:
运行结果


函数指针:

概念:函数指针是指向函数的指针变量。因而“函数指针”本身首先应该是指针变量,只不过该指针变量指向函数。这正如指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样。函数指针有两个用途:调用函数和做函数的参数。

定义形式:返回值类型 (*指针变量名)(函数形参列表)
说明:同样,这里的括号不可少,也是要考虑运算符的优先级

用函数指针调用函数:

#include<stdio.h>

void Test();

int main()
{
    void (*p)();               //声明一个函数指针(无返回值,无形参)

    p=Test;                    //或者用 p = &Test; 将函数的入口地址传给 p
    p();

    return 0;

void Test()
{
    printf("我被调用了!\n");
}

用函数指针作函数的参数:

#include<stdio.h>

void Fun(int i);
void useFun(void (*p)(int m),int i);       
//这里将 void (*p)(int m) 作为useFun函数的一个形参

int main()
{
    void (*p)(int m);          //声明一个函数指针

    p=Fun;               
    useFun(p,10);             //调用函数,注意这里将一个函数指针作为了形参

    return 0;
}

void Fun(int i)
{
    printf("我被调用于输出:%d",i);
}
void useFun(void (*p)(int m),int i)
{
    p(i);                           //调用函数
}

二级指针:

概念:二级指针既是指针的指针。一级指针 *p 是用于存放一个变量 a 的地址的,即是通过这个一级指针我们可以对变量 a 进行操作;一级指针 *p 事实上也是变量,我们也需要对它进行一些操作,那么就用另一个指针变量来保存这个一级指针的地址,这就是二级指针 **p

如图:
二级指针图示
这里存在一个变量 C ,B 为一级指针,A 为二级指针。C 中存放了一个数据,而 B 存放着 C 的地址,A 又存放着B的地址。

二级指针可分为:指向指针变量的指针、指向数组的指针

前者不再举例,下面给出一个指向数组的指针实例

#include<stdio.h>
int main()
{
    int i,a[5]={1,2,3,4,5};
    int *p,**pp;                  //定义一个一级指针 p 和一个二级指针 pp

    p=a;
    pp=&p;
        for(i=0;i<5;i++)          //用二级指针变量输出方式一
        printf("%d\t",*(*pp+i));

    printf("\n");

    for(i=0;i<5;i++,p++)          //用二级指针变量输出方式二
        printf("%d\t",**pp);
    return 0;
}

至此,笔者能写的就这么多,下面再进行一下总结。

1、普通指针用于存放某变量的地址
2、指针数组是一系列同类型指针构成的一个数组
3、数组指针用于指向数组地址。以二维数组指针为例,数组指针就是用于存放二维数组一行所构成的一个一维数组的首地址。
4、指针函数是函数,其函数返回值为某一类型的指针
5、函数指针是函数,其指向某个函数,存放某个函数的入口地址值
6、二级指针是指针的指针,是用于存放某个指针变量的地址的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
指针是一个未指向任何有效内存地址的指针。在C语言中,可以使用NULL常量来表示空指针。当一个指针被赋值为NULL时,它就成为了一个空指针。空指针通常用于表示指针不指向任何有效的对象或内存空间。引用中的代码示例中,使用了一个条件判断`if(!p)`来确保结构体指针不为空指针。 结构体是一种用户自定义的数据类型,可以将不同类型的数据组合在一起以形成一个结构。结构体可以包含多个成员变量,每个成员变量可以是不同的数据类型,比如整型、字符型、浮点型等。通过结构体能够更好地组织和管理相关的数据。 在C语言中,可以通过定义结构体变量和结构体指针来使用结构体。结构体变量是直接存储结构体的实例,而结构体指针则存储了结构体实例的内存地址。引用中的代码示例展示了如何定义和使用结构体以及使用结构体指针修改结构体变量的值。 需要注意的是,在使用结构体指针时,需要确保指针不为空指针,以避免发生错误。可以通过条件判断来判断指针是否为空,如`if(!p)`。 总结来说,C语言的空指针和结构体是两个不同的概念。空指针是指向空地址的指针,用于表示指针不指向任何有效的对象或内存空间。而结构体是一种用户自定义的数据类型,用于组合不同类型的数据。结构体可以通过结构体变量和结构体指针来使用,并通过指针来修改结构体变量的值。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [C语言指针与结构体](https://blog.csdn.net/weixin_44969353/article/details/126185425)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [C语言结构体指针与结构体变量作形参的区别](https://blog.csdn.net/qq_42759112/article/details/119275822)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值