指针相关概念

本文介绍了指针的基本概念,包括指针数组、数组指针、函数指针以及函数指针数组。重点阐述了数组在传参时会退化为指针,以及如何判断变量类型。最后探讨了函数指针数组的使用和应用实例,帮助读者深入理解指针的运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通俗的说,指针就是地址;指针变量是变量,是一个用来存放地址的变量。
1.指针数组
指针数组是一个可以存放指针的数组。
例:

int *arr1[10]; char *arr2[4];

2.数组指针
数组指针是指向数组的一个指针。
例:

int (*p)[10];  //p代表数组指针
int *p[10];   //p代表指针数组

注意:
(1)[ ]的优先级要高于号的,所以加上()保证p先和结合;
(2)以后我们判断一个变量的类型时,只需要看它的优先级即可,若变量先和数组结合,那么该变量就是一个数组;若变量先和*结合,那说明此变量是一个指针。

数组指针的使用:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int arr[10] = { 0 };
    printf("%p\n", arr);  //008FFE58  arr:表示数组首元素地址;
    printf("%p\n", arr+1); //008FFE5C arr+1:表示第二个元素的地址;
    printf("%p\n", &arr+1); //008FFE80 &arr:表示数组的地址;&arr+1:表示该数组下一个数组的地址;
    system("pause");
    return 0;
}

数组在传参时需要:
(1)所有的数组都会降为一维数组;
(2)数组传参会退化为指针;
(3)该指针指向其内部元素类型。

二维数组传参:

void test(int arr[3][5])  //正确
{}
void test(int arr[][])  //错误
{}
void test(int arr[][5])  //正确
{}
//总结:二维数组传参时,函数形参只能省略第一个[]的数字。以后多维数组也一样,只能省略第一个参数。
void test(int *arr)  //类型不匹配
{}
void test(int *arr[5]) //类型不匹配,这是指针数组
{}
void test(int (*arr)[5])  //正确,是数组指针
{}
int main()
{
   int arr[3][5] = {0};
   test(arr);
}

3.函数指针

函数指针是一个变量,用来存放函数(即代码)的地址。

#include <stdio.h>
#include <stdlib.h>

void test()
{
    printf("hehe\n");
}
int main()
{
    printf("%p\n", test);  //000E12AD
    printf("%p\n", &test);  //000E12AD
    system("pause");
    return 0;
}

输出的两个地址一样,因为test和&test的结果都是数组首元素的地址,但意义完全不同;test代表首元素地址,&test代表整个数组的地址。
下面我们看这段代码:

void test()
{
   printf("hehe\n");
}
void (*pfun1)();  //函数指针;
void *pfun2();   //函数的声明;

指针就是地址,故pfun1可以存放函数的地址。因为pfun1先和*结合,说明pfun1是个指针,指针指向一个函数,即为函数指针。

阅读两段有趣的代码:

(*(void (*) ())0) (); //如何理解?
//(void (*) ())0) 先将0强转成函数指针,然后解引用,即调用0地址处的内容。
void (*signal(int,void(*)(int)))(int);  //函数的声明;

4.函数指针数组
把函数的地址存到一个数组中,那这个数组就叫函数指针数组。
判断下面哪个是函数指针数组:

int (*parr1[10])();
int *parr2[10]();
int (*)()parr3[10];

结果是:parr1.
parr1先和[ ]结合,说明parr1是数组,存放的内容是int(*)()类型的函数指针。

函数指针数组的应用实例:转移表


#include <stdio.h>
#include <stdlib.h>

int my_add(int x, int y)
{
    return x + y;
}
int my_sub(int x, int y)
{
    return x - y;
}
int my_mul(int x, int y)
{
    return x * y;
}
int my_div(int x, int y)
{
    return x / y;
}

int main()
{
    int input = 0;
    int x = 0;
    int y = 0;
    int(*p[5])(int x, int y) = { my_add,my_sub,my_mul,my_div};
    int ret = 0;
    while (1)
    {
        printf("********************\n");
        printf("* 0.add      1.sub *\n");
        printf("* 2.mul      3.div *\n");
        printf("*            4.exit*\n");
        printf("********************\n");
        printf("请选择:>");
        scanf("%d", &input);
        if (input >= 0 && input <= 3)
        {
            printf("请输入x,y的值 :");
            scanf("%d %d", &x, &y);
            ret = (*p[input])(x, y);
        }
        else if (input == 4)
        {
            printf("确认退出!\n");
            break;
        }
        else
        {
            printf("输入错误,请重新选择:>");
        }
        printf("%d\n", ret);
    }
    system("pause");
    return 0;
}

5.函数指针数组的指针
把指针指向一个数组,数组的元素都是函数指针的指针称为函数指针数组的指针。
例:

void test(const char* str)
{
    printf("%s\n", str);
}
int main()
{
    //pfun是函数指针
    void(*pfun)(const char *) = test;
    //pfunArr是函数指针数组
    void(*pfunArr[5])(const char * str);
    pfunArr[0] = test;
    //ppfunArr是指向函数指针数组pfunArr的指针
    void(*(*ppfunArr)[10])(const char *) = &pfunArr;
    system("pause");
    return 0;
}
### 指针概念与基础知识 指针是C语言中一个非常重要的概念,它允许程序直接访问内存地址并操作存储在这些地址中的数据。指针的引入极大地提高了程序的灵活性和效率[^2]。 #### 1. 指针的基本定义 指针是一个变量,其值为另一个变量的地址,即内存位置。通过指针,可以直接访问和修改该地址上的数据。指针的声明方式如下: ```c type *pointer_name; ``` 其中,`type`表示指针所指向的变量类型,`*`表示这是一个指针变量,`pointer_name`是用户定义的指针名称。 #### 2. 指针的初始化与使用 在声明指针后,需要将其初始化为某个变量的地址。可以通过取地址运算符`&`获取变量的地址。例如: ```c int a = 10; int *p = &a; // p 是指向整型变量 a 的指针 ``` 通过解引用运算符`*`,可以访问指针所指向的变量的值。例如: ```c printf("%d", *p); // 输出变量 a 的值 ``` #### 3. 指针的用途 - **动态内存分配**:通过指针可以实现动态内存分配,例如使用`malloc()`或`calloc()`函数。 - **函数参数传递**:指针可以用于传递数组或结构体等复杂数据类型的地址,从而避免拷贝整个数据结构。 - **数组与指针的关系**:在C语言中,数组名本质上是一个指向数组首元素的常量指针。例如: ```c int arr[5] = {1, 2, 3, 4, 5}; int *p = arr; // p 指向数组的第一个元素 ``` #### 4. 指针的注意事项 - **空指针**:未初始化的指针可能会指向未知的内存地址,因此在使用前应确保其被正确初始化。可以将指针初始化为`NULL`以避免潜在问题。 - **野指针**:指针在释放内存后未被置为`NULL`,可能导致访问非法内存区域。 - **指针算术**:指针支持加减运算,但必须注意越界访问的问题。 #### 示例代码 以下是一个简单的指针示例,展示了如何使用指针交换两个整数的值: ```c void swap(int *x, int *y) { int temp = *x; *x = *y; *y = temp; } int main() { int a = 5, b = 10; printf("Before swap: a = %d, b = %d\n", a, b); swap(&a, &b); printf("After swap: a = %d, b = %d\n", a, b); return 0; } ``` 指针概念不仅限于C语言,在其他编程语言中也有类似的思想,例如C++中的智能指针、Java中的引用等。掌握指针的基础知识对于理解更高级的数据结构(如链表、树和图)至关重要[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值