指针与函数和结构体

做计算机二级的时候发现指针对函数和结构体的题目主要出现在选择题上,之前学的不清楚,导致在看到题的时候有种懵懵的感觉,之前对二维数组和指针的复习还不错,于是照着之前的方式开始翻书复习、网上查阅。博客记录等来了解和学习。

指针与函数

指针与函数分为函数指针和指针函数

函数指针

函数指针就是返回值是指针的函数,这个无需多说,只要明白函数的返回值的定义就容易懂。

指针函数

可以这样说,指针指向一个函数,本人对指针比较迷,所以多深入了解一下。
本次参考的讲解:点击直达
首先需要明白,函数名就是地址,与数组名很相似。
指针函数int (*p0)(int x)=fun;,使p0指针指向fun函数。在用的时候可以通过p()直接进行调用,也可以通过(*p)()进行调用。
为什么可以通过(*p)()调用,网上没有准确的答案,在这我也只能认为是(*p)是fun函数名称之后退化为指针形式p在进行调用。(不保证正确性)

#include<stdio.h>
int fun(int x)
{
    return x+x;
}
void main()
{
    int (*p0)(int x);
    p0=fun;
    printf("%d\n",fun(1));
    printf("%d\n",p0(1));
    printf("%d\n",(*p0)(1));
}

运行结果:

2
2
2

复杂指针,通过返回值是函数指针在进行下一个函数。int(*(*p1)(int))(int),先看中间斜体部分,可以看出他和上面的指针函数是相同的,如果指针函数返回值是一个函数指针,那么将斜体部分看成指针p1的话就变成了int (p1)(int),这是个函数。因此只要斜体部分返回值是指针函数那么就能用复杂指针去调用函数。

#include<stdio.h>
int fun1(int x)
{
    printf("到了fun1,接收到的值为%d,地址为:%d\n",x,fun1);
    return 0;
}
int (*(fun)(int x))(int)
{
    printf("经过了fun,接收到的值为%d,地址为:%d\n",x,fun);
    return fun1;
}
void main()
{
    int(*(*p1)(int))(int);
    p1=fun;
    p1(100)(10);
}

运行结果:

经过了fun,接收到的值为100,地址为:8655343
到了fun1,接收到的值为10,地址为:8655353

从运行结果来看,显示到达了fun函数,100传递给fun函数的x,之后fun函数返回了fun1函数的地址,之后运行了fun1函数,将10传递给了fun1的x。
解释一下:int((p1)(int))(int)这段定义:从左至右来看,第一个int的定义的是fun和fun1的函数类型为int的,第一步到fun函数时fun函数的类型为int,那么fun函数返回值也必定是int类型的指针,而后面两个int的是形参,因此可以是任意类型的。

函数类型定义
通过typedef别名对函数指针进行定义typedef int(*p2)(int);,通过这个语句可以定义为p2为一个函数指针类型。接下来就可以直接用p2进行定义函数。

#include<stdio.h>
typedef int(*p2)(int);
int fun1(int x)
{
    printf("到了fun1,接收到的值为%d,地址为:%d\n",x,fun1);
    return 0;
}
p2 fun2(int x)
{
    printf("经过了fun2,接收到的值为%d,地址为:%d\n",x,fun2);
    return fun1;
}

void main()
{
    fun2(2)(4);
}

运行结果:

经过了fun2,接收到的值为2,地址为:20189399
到了fun1,接收到的值为4,地址为:20189639

指针与结构体

指针与结构体部分早前已经在代码备注里面写了,所以也不多做分析了。对结构体的成员的调用方法例如下面实例中的date3.year,通过:结构体变量名.成员名 来直接用。结构体针对指针有方便的调用方法指向(->),例如下面实例中的p->year,这就放方便了通过指针来调用成员的步骤。因此我们只要通过结构体类型的指针就能指向结构体类型的变量。主要将的是指针与结构体的关系,所以关于结构体其他方面不多说。而下面代码就很好的解释了关联。(不包括链表内容)

#include<stdio.h>
struct date
{
    int year;
    int month;
    int day;
    int time[3];
};
int main()
{
    struct date *p,date1[2]={{1,2,3,10,20,30},{2,3,4,14,24,35}},date2={4,5,6,7,8,9},date3={0,0,0,0,0,0};//定义date类型指针、数组、变量
    printf("我验证结构体变量之间可以直接赋值\n");
    printf("%d %d %d %d %d %d\n",date3.year,date3.month,date3.day,date3.time[0],date3.time[1],date3.time[2]);
    date3=date2;//结构体变量之间可以直接赋值,里面即使有数组也一样,但直接通过数组名进行赋值是不可以的。
    printf("%d %d %d %d %d %d\n",date3.year,date3.month,date3.day,date3.time[0],date3.time[1],date3.time[2]);
    printf("我是通过结构体变量名直接输出的\n");
    int i,j;
    for(i=0;i<2;i++)//通过结构体变量直接输出
    {
        printf("%d %d %d ",date1[i].year,date1[i].month,date1[i].day);
        for(j=0;j<3;j++)
            printf("%d ", date1[i].time[j]);
        printf("\n");
    }
    printf("我是通过结构体指针输出的\n");
        for(p=date1,i=0;i<2;i++)//date1是数组名,通过将p(同样以数组形式)将结构体数组输出
    {
        printf("%d %d %d ",p[i].year,p[i].month,p[i].day);
        for(j=0;j<3;j++)
            printf("%d ", p[i].time[j]);
        printf("\n");
    }
    printf("我是通过结构体指针通过p的指向结构体变量地址输出的\n");
        for(p=date1;p-date1<2;p++)//date1是数组名,通过将p的指向将结构体数组输出
    {
        printf("%d %d %d ",p->year,p->month,p->day);
        for(j=0;j<3;j++)
            printf("%d ", p->time[j]);
        printf("\n");
    }
        printf("我是通过结构体指针通过p的指向结构体变量地址并通过p1指向p->time将time数组输出的\n");
        int *p1;//date1是数组名,通过将p的指向将结构体数组,在通过p1指向p->time将time数组输出
        for(p=date1;p-date1<2;p++)
    {
        printf("%d %d %d ",p->year,p->month,p->day);
        for(p1=p->time;p1-p->time<3;p1++)
        {
            printf("%d ",*p1);
        }
        printf("\n");
    }
}

运行结果:

我验证结构体变量之间可以直接赋值
0 0 0 0 0 0
4 5 6 7 8 9
我是通过结构体变量名直接输出的
1 2 3 10 20 30
2 3 4 14 24 35
我是通过结构体指针输出的
1 2 3 10 20 30
2 3 4 14 24 35
我是通过结构体指针通过p的指向结构体变量地址输出的
1 2 3 10 20 30
2 3 4 14 24 35
我是通过结构体指针通过p的指向结构体变量地址并通过p1指向p->time将time数组输出的
1 2 3 10 20 30
2 3 4 14 24 35

添加新评论