赞
踩
1、二维数组的本质
在 C 语言中,二维数组本质上是由多个一维数组组成的。例如,int a[2][3]可以看作是包含两个长度为 3 的一维整数数组。
2、指针与二维数组
对于二维数组int a[2][3],&a[0]的类型是int (*)[3],因为 C 语言中不直接支持int[3] *这种类型,所以需要使用int (*)[3]来表示指向包含 3 个整数的一维数组的指针。
定义指针int (*p)[3] = a;p指向了二维数组a的首地址,其基类型是int[3]。
3、通过指针访问二维数组元素
*p相当于a[0],即指向二维数组的第一行(内部的一维数组)。
(*p)[0]表示第一行的第一个元素,等同于a[0][0]。
*(*p + 0)也表示第一行的第一个元素。
*(*(p + 1) + 1)相当于a[1][1],即指向二维数组的第二行的第二个元素。
一般地,*(*(p + i) + j)就相当于a[i][j],可以通过这种方式遍历二维数组的元素。
例如,如果要通过指针遍历二维数组a的所有元素,可以使用以下代码:
- for (int i = 0; i < 2; i++)
- {
- for (int j = 0; j < 3; j++)
- {
- printf("%d ", *(*(p + i) + j));
- }
- printf("\n");
- }
4、将二维整型数组作为参数传递给函数
以数组形式传递:第二维的大小必须指定
- void function(int arr[][3], int rows)
- {
- // 函数体
- }
-
- int main()
- {
- int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
- function(a, 2);
- return 0;
- }
以指针形式传递:这种方式与以数组形式传递本质上是相同的
- void function(int (*arr)[3], int rows)
- {
- // 函数体
- }
-
- int main()
- {
- int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
- function(a, 2);
- return 0;
- }
char s[][10] = {"hello","world","china"};
char (*p)[10] = s;
定义了一个指针 p ,它指向一个包含 10 个字符的一维字符数组,这里 p 指向了二维数组 s 的起始位置。
*(*(p + i) + j) 可以用于访问二维字符型数组 s 中特定位置的字符。
- void putStr(char (*p)[10], int row)
- {
- int i=0;
- for ( i=0; i<3; i++ )
- {
- printf("%s \n",*(p+i));
- }
- }
- int main()
- {
-
- char s[][10] = {"hello","world","China"};
- char (*p)[10] = s;
-
- putStr(s,3);
-
- return 0;
- }

1、函数指针的概念
函数指针是一种特殊的指针,它指向函数的入口地址。函数指针的类型由函数的返回值类型和参数类型共同决定。
2、函数指针的定义和初始化
在代码中,例如:
int (*p)(int);
定义了一个函数指针 p
,它指向一个返回值为 int
且有一个 int
类型参数的函数。
可以通过将函数名赋给函数指针来进行初始化,如 p = func1;
。
例:
- // 定义一个指向返回值为 int,带有两个 int 型参数的函数的指针
- int (*ptr)(int, int);
可以将函数的地址赋给函数指针,例如,如果有函数 int add(int a, int b) ,则可以这样赋值:
ptr = add;
int result = ptr(2, 3); // 等价于 int result = add(2, 3);
3、回调函数
回调函数是一种通过函数指针实现的机制。在某些情况下,一个函数(通常称为主调函数)可能在执行过程中需要调用另一个函数(回调函数)来完成特定的任务。主调函数事先不知道回调函数的具体实现,但通过传递函数指针来在需要的时候调用它。
- #include <stdio.h>
-
- // 定义一个函数,返回输入参数的值
- int func1(int n)
- {
- return n;
- }
-
- // 定义一个函数,返回输入参数的平方
- int func2(int n)
- {
- return n*n;
- }
-
- // 定义一个函数,返回输入参数的立方
- int func3(int n)
- {
- return n*n*n;
- }
-
- // 选择排序函数,根据传入的函数指针确定排序规则
- void choieSortN(int *a, int len, int (*p)(int))
- {
- int i = 0;
- int j = 0;
-
- for (i = 0; i < len - 1; i++) // 外层循环控制排序轮数
- {
- for (j = i + 1; j < len; j++) // 内层循环每一轮比较次数
- {
- if (p(a[i]) > p(a[j])) // 根据传入的函数计算值进行比较
- {
- int temp = a[i]; // 交换元素
- a[i] = a[j];
- a[j] = temp;
- }
- }
- }
- }
-
- // 打印数组函数
- void printfArray(int *a, int len)
- {
- int i = 0;
- for (i = 0; i < len; i++) // 遍历数组并打印每个元素
- {
- printf("%d ", a[i]);
- }
- printf("\n"); // 换行
- }
-
- // 定义加法函数
- int ADD(int a, int b)
- {
- return a + b;
- }
-
- // 定义减法函数
- int SUB(int a, int b)
- {
- return a - b;
- }
-
- // 定义乘法函数
- int MUL(int a, int b)
- {
- return a * b;
- }
-
- // 定义除法函数
- int DIV(int a, int b)
- {
- return a / b;
- }
-
- // 处理数据函数,根据传入的函数指针进行计算并打印结果
- void processDate(int a, int b, int (*p)(int, int))
- {
- printf("ret = %d\n", p(a, b)); // 打印计算结果
- }
-
- int main()
- {
- int a[] = {6, -7, 3, -9, 5, 1, 8, -4, 2}; // 定义并初始化整数数组
- int len = sizeof(a) / sizeof(a[0]); // 计算数组长度
-
- choieSortN(a, len, func1); // 以 func1 规则排序
- printfArray(a, len); // 打印排序后的数组
- choieSortN(a, len, func2); // 以 func2 规则排序
- printfArray(a, len); // 打印排序后的数组
- choieSortN(a, len, func3); // 以 func3 规则排序
- printfArray(a, len); // 打印排序后的数组
-
- processDate(3, 2, ADD); // 计算 3 和 2 的加法
- processDate(3, 2, SUB); // 计算 3 和 2 的减法
- processDate(3, 2, MUL); // 计算 3 和 2 的乘法
- processDate(3, 2, DIV); // 计算 3 和 2 的除法
-
- return 0;
- }

4、回调函数的实现
choieSortN 函数是一个排序函数,它接受一个整数数组 a 、数组长度 len 和一个函数指针 p 作为参数。在函数内部,通过比较 p(a[i]) 和 p(a[j]) 的结果来进行排序。这就是回调函数的应用,通过传递不同的函数指针(如 func1 、 func2 、 func3 ),可以实现基于不同规则的排序。
processDate 函数接受两个整数 a 、 b 和一个函数指针 p ,通过 p(a, b) 来调用传入的函数进行计算,并打印结果。
5、函数指针的用途
增加代码的灵活性和可扩展性,使得主调函数可以根据不同的需求调用不同的回调函数。
实现事件驱动编程,当特定事件发生时,调用相应的处理函数。
封装和隐藏函数的实现细节,只暴露函数指针供外部使用。
指针的指针(也称为二级指针)是指向指针的指针变量。
- #include <stdio.h>
-
- int main()
- {
- int num = 10; // 定义一个整数变量
-
- int *ptr = # // 定义一个指针指向 num
-
- int **ptrPtr = &ptr; // 定义一个二级指针指向 ptr
-
- // 通过二级指针访问和修改 num 的值
- printf("初始值:%d\n", **ptrPtr);
-
- **ptrPtr = 20; // 修改 num 的值
-
- printf("修改后的值:%d\n", **ptrPtr);
-
- return 0;
- }

在上述代码中:
int num = 10; 定义了一个整数 num ,值为 10 。
int *ptr = # 定义了一个指针 ptr ,并使其指向 num 。
int **ptrPtr = &ptr; 定义了一个二级指针 ptrPtr ,并使其指向指针 ptr 。
通过二级指针,可以间接访问和修改其所指向的指针所指向的变量的值。
指针的指针常用于一些复杂的数据结构,如链表、二叉树等,或者在函数中需要修改指针的值时使用。
指针数组是一个数组,其中的每个元素都是一个指针。
- #include <stdio.h>
-
- int main()
- {
- // 定义三个整数变量
- int num1 = 10, num2 = 20, num3 = 30;
-
- // 定义一个指针数组,每个元素都是指向 int 类型的指针
- int *ptrArray[] = {&num1, &num2, &num3};
-
- // 通过指针数组访问和打印变量的值
- for (int i = 0; i < 3; i++)
- {
- printf("%d ", *(ptrArray[i]));
- }
- printf("\n");
-
- return 0;
- }

代码中定义了一个指针数组 ptrArray ——int *ptrArray[] = {&num1, &num2, &num3}; 并将三个整数变量的地址分别存储在数组的元素中。在 for 循环中,通过 *(ptrArray[i]) 来获取每个指针所指向的整数的值并进行打印。
指针数组是一个数组,其中的每个元素都是一个指针。
int* arr1[5]; // 定义了一个包含 5 个指向 int 类型的指针的数组
arr1
是一个指针数组,它的每个元素都可以用来指向一个 int
类型的变量。
数组指针是指向一个数组的指针。
int (*arr2)[5]; // 定义了一个指向包含 5 个 int 类型元素的数组的指针
要区分指针数组和数组指针,可以通过以下方式记忆:
指针数组:先看“数组”,意味着这是个数组,再看“指针”,说明数组中的元素是指针。
数组指针:先看“指针”,表示这是个指针,再看“数组”,表明指针指向的是一个数组。
- #include <stdio.h>
-
- int main()
- {
- int num1 = 10, num2 = 20, num3 = 30, num4 = 40, num5 = 50;
-
- // 指针数组的使用
- int* ptrArray[5] = {&num1, &num2, &num3, &num4, &num5};
-
- for (int i = 0; i < 5; i++)
- {
- printf("指针数组中第 %d 个元素指向的值: %d\n", i, *ptrArray[i]);
- }
-
- // 数组指针的使用
- int arr[3][5] =
- {
- {1, 2, 3, 4, 5},
- {6, 7, 8, 9, 10},
- {11, 12, 13, 14, 15}
- };
-
- int (*ptr)[5] = arr;
-
- for (int i = 0; i < 3; i++)
- {
- for (int j = 0; j < 5; j++)
- {
- printf("数组指针指向的数组中第 %d 行第 %d 列的值: %d\n", i, j, (*ptr)[j]);
- }
- ptr++; // 移动指针指向下一行
- }
-
- return 0;
- }

- #include <stdio.h>
-
- // 主函数,接收命令行参数
- int main(int argc, const char *argv[])
- {
- // 打印命令行参数的数量
- printf("argc = %d\n", argc);
-
- int i = 0;
- // 遍历所有的命令行参数
- for (i = 0; i < argc; i++)
- {
- // 打印每个参数的索引和参数值
- printf("argv[%d] = %s\n", i, argv[i]);
- }
-
- return 0;
- }

这段代码主要用于处理命令行参数。 在 `main` 函数中,`argc` 表示命令行参数的数量,包括程序名本身。 `argv` 是一个字符指针数组,其中每个元素指向一个命令行参数的字符串。 例如,在命令行中运行 `./a.out arg1 arg2 arg3` 时: - `argc` 的值为 `4`,因为有程序名 `./a.out` 以及三个参数 `arg1`、`arg2`、`arg3`。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。