【C语言】指针进阶:掌握指针数组和指向指针的指针

【C语言】指针进阶:掌握指针数组和指向指针的指针本文介绍了 C 语言中指针进阶的内容 字符指针 指针数组 数组指针 函数指针 并给出了函数指针数组的简易计算示例

大家好,欢迎来到IT知识分享网。

每日一图:
在这里插入图片描述

本篇内容:

  • 1.字符指针
  • 2.指针数组
  • 3.数组指针
    • 3.1数组指针的定义
    • 3.2&数组名和数组名的区别
    • 3.3数组指针的使用
  • 4.数组参数和指针参数
    • 4.1一维数组传参
    • 4.2二维数组传参
    • 4.3一级指针传参
    • 4.4二级指针传参
  • 5.函数指针
  • 6.函数指针数组
    • 简易计算器
  • 7.指向函数指针数组的指针

1.字符指针

int main() { 
    char ch = "a"; char* pc = &ch; return 0; } 

这里的pc就是一个字符指针变量,这种方法是让我们的字符指针指向了一个字符变量。

另一种使用方式如下:
把字符串首字符的地址赋给了一个指针。

int main() { 
    const char* p = "Hello World"; return 0; } 

因为这个字符串是一个常量字符串(不能被修改)所以在char*前面加一个const会更加严谨。

2.指针数组

指针数组就是存放指针的数组或存放地址的数组。

存放字符指针的数组:

int main() { 
    const char* arr[4] = { 
    "abcd,qwer,asdf,zxcv" }; return 0; } 

这四个字符串的首字符的地址都被放在了指针数组arr中。

打印:

int main() { 
    const char* arr[4] = { 
    "abcd","qwer","asdf","zxcv" }; int i = 0; for (i = 0; i < 4; i++) { 
    printf("%s\n", arr[i]); } return 0; } 

存放整形指针的数组:

int main() { 
    int arr1[5] = { 
    1,2,3,4,5 }; int arr2[5] = { 
    2,3,4,5,6 }; int arr3[5] = { 
    3,4,5,6,7 }; int arr4[5] = { 
    4,5,6,7,8 }; int* arr[4] = { 
    arr1,arr2,arr3,arr4 }; return 0; } 

打印:

int main() { 
    int arr1[5] = { 
    1,2,3,4,5 }; int arr2[5] = { 
    2,3,4,5,6 }; int arr3[5] = { 
    3,4,5,6,7 }; int arr4[5] = { 
    4,5,6,7,8 }; int* arr[4] = { 
    arr1,arr2,arr3,arr4 }; int i = 0; for (i = 0; i < 4; i++) { 
    int j = 0; for (j = 0; j < 5; j++) { 
    printf("%d ", arr[i][j]); } printf("\n"); } return 0; } 

3.数组指针

3.1数组指针的定义

数组指针 – 存放数组地址的指针 – 指向数组的指针

数组指针的写法:

 int arr[10]; int (*pa)[10] = &arr; 

3.2&数组名和数组名的区别

先来看一段代码:

int main() { 
    int arr[10] = { 
    1,2,3,4,5,6,7,8,9,10 }; printf("%p\n", arr); printf("%p\n", arr + 1); printf("%p\n", &arr[0]); printf("%p\n", &arr[0] + 1); printf("%p\n", &arr); printf("%p\n", &arr + 1); return 0; } 

3.3数组指针的使用

void print1(int(*p)[4],int r,int c) { 
    int i = 0; for (i = 0; i < r; i++) { 
    int j = 0; for (j = 0; j < c; j++) { 
    printf("%d ", (*(p + i))[j]);//或printf("%d ", p[i][j]); } printf("\n"); } } int main() { 
    int arr[3][4] = { 
    { 
   1,2,3,4},{ 
   2,3,4,5},{ 
   6,7,8,9} }; print1(arr, 3, 4); return 0; } 

4.数组参数和指针参数

函数的参数应该如何设计呢?

4.1一维数组传参

一维数组传参的时候形参该如何写?

void test(int arr[]) { 
   } void test(int arr[10]) { 
   } void test(int* arr) { 
   } void test2(int* arr[20]) { 
   } void test2(int** arr) { 
   } int main() { 
    int arr[10] = { 
    0 }; int* arr2[20] = { 
    0 }; test(arr); test2(arr2); } 

以上方法均可

4.2二维数组传参

二维数组传参的时候形参该如何写?

void test(int arr[3][5]) { 
   } void test(int arr[][5]) { 
   } //总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。 //因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。 //这样才方便运算。 void test(int(*arr)[5]) { 
   } int main() { 
    int arr[3][5] = { 
    0 }; test(arr); } 

以上方法均可

4.3一级指针传参

指针变量传参,指针变量接收

#include <stdio.h> void print(int *p, int sz) { 
    int i = 0; for(i=0; i<sz; i++) { 
    printf("%d\n", *(p+i)); } } int main() { 
    int arr[10] = { 
   1,2,3,4,5,6,7,8,9}; int *p = arr; int sz = sizeof(arr)/sizeof(arr[0]); //一级指针p,传给函数 print(p, sz); return 0; } 

当一个函数的参数部分为一级指针的时候,函数能接收什么参数?

void test(int* p) { 
   } int main() { 
    int a = 10; int* p = &a; int arr[10]; test(p);//可以传一级指针 test(arr);//可以传一维数组的数组名 test(&a);//可以传整型变量的地址 return 0; } 

4.4二级指针传参

void test(int** ptr) { 
    printf("num = %d\n", **ptr); } int main() { 
    int n = 10; int* p = &n; int** pp = &p; test(pp); test(&p); return 0; } 

二级指针传参,形参部分用二级指针接收。

当函数的参数为二级指针的时候,可以接收什么参数?

void test(int** p) { 
   } int main() { 
    int** ptr; int* pp; int* arr[10]; test(ptr);//可以传二级指针变量 test(&pp);//可以传一级指针变量的地址 test(arr);//可以传指针数组的数组名 return 0; } 

5.函数指针

前面我们讲到了数组指针:指向数组的指针。

 inr arr[10]; int (*p) [10] = &arr; 

那么函数指针是什么呢?其实就是指向函数的指针
其实函数也是有地址的,我们来看下面这条代码:

int Add(int x, int y) { 
    return x + y; } int main() { 
    printf("%p\n", &Add); return 0; } 

运行效果:

在这里插入图片描述
可以看到,我们把Add函数的地址打印了出来。
那么函数指针应该怎么写呢?很简单,我们看下面这条代码:

int Add(int x, int y) { 
    return x + y; } int main() { 
    int (*pf)(int,int) = &Add; //pf是一个存放函数地址的指针变量 — 函数指针 return 0; } 
int (*pf)(int, int) = Add; 
 int (*pf)(int, int) = Add; int ret = (*pf)(2, 3);//或int ret = pf(2,3); printf("%d\n", ret); 

首先pf是个指针,指针解引用才能找到对应的函数(可以省略为pf,但方便理解我们还是写上:(*pf),调用的时候要传参,那我们就传个2和3:(*pf)(2,3),传过去之后函数计算完结果,那我们就把结果放在ret里面:int ret = (*pf)(2,3);

6.函数指针数组

想要写出函数指针数组,要从函数指针的基础上进行改造。

int (*pf)(int,int) = &Add;//函数指针 int (*pfA[5])(int,int) ={ 
   &Add};//函数指针数组 

简易计算器

#include<stdio.h> void menu() { 
    printf("\n"); printf("* 1.add 2.sub *\n"); printf("* 3.mul 4.div *\n"); printf("* 0.exit *\n"); printf("\n"); } int Add(int x, int y) { 
    return x + y; } int Sub(int x, int y) { 
    return x - y; } int Mul(int x, int y) { 
    return x * y; } int Div(int x, int y) { 
    return x / y; } //函数指针数组存放上述函数的地址 //转移表 int (*pf[5])(int, int) = { 
    0,Add,Sub,Mul,Div }; //输入1对应Add,输入2对应Sub //输入3对应Mul,输入4对应Div int main() { 
    int input = 0; int x = 0; int y = 0; int ret = 0; do { 
    menu(); printf("请选择->"); scanf("%d", &input); if (input == 0) { 
    printf("退出计算器\n"); break; } else if (input >= 1 && input <= 4) { 
    printf("请输入两个操作数\n"); scanf("%d %d", &x, &y); ret = pf[input](x, y);//通过输入数调用函数 printf("%d\n", ret); } else { 
    printf("选择错误,请重新选择\n"); } } while (input); return 0; } 

这里的函数指针数组代替了switch函数,简化了很多代码,但是他也有缺点:因为函数指针数组限制了他(函数里的参数类型、返回类型必须一致),所以他只能计算双目操作数。

7.指向函数指针数组的指针

int (*pf[5])(int, int); 

这里的pf和[]结合说明他是一个数组,但是我们希望他是指针,那我们就在这个基础上进行修改:

int (*pf[5])(int, int);//函数指针数组 int (*(*ppf)[5])(int, int) = &pf;//ppf - 指向函数指针数组的指针 

我们只需要加上*然后再把ppf括起来,这时候ppf就是一个指针了。

以上就是本篇的全部内容了,希望大家看完能有所收获。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/120611.html

(0)
上一篇 2025-10-28 16:33
下一篇 2025-10-28 17:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信