🌟 各位看官好,我是maomi_9526!
🌍 种一棵树最好是十年前,其次是现在!
🚀 今天来学习C语言的相关知识。
👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦
目录
1. 字符指针变量
-
定义:字符指针
char*
用于存放字符类型变量的地址。 -
例子1:
char ch = 'w'; char *pc = &ch; *pc = 'w';
-
例子2:常量字符串的字符指针
const char* pstr = "hello bit."; printf("%s\n", pstr);
- 解释:
pstr
存储的是字符串"hello bit."
的首字符地址,而不是字符串本身。
- 解释:
-
比较字符串:
char str1[] = "hello bit."; char str2[] = "hello bit."; const char *str3 = "hello bit."; const char *str4 = "hello bit.";
- 结果:
str3
和str4
指向相同的内存区域,而str1
和str2
存储在不同的内存块。
- 结果:
2. 数组指针变量
-
定义:数组指针变量是指向数组的指针,指向整个数组而非数组元素。
-
例子:
int (*p)[10] = &arr;
p
是一个指向包含 10 个整数的数组的指针。
-
数组指针的初始化:数组指针指向数组的地址。
int arr[10] = {0}; int (*p)[10] = &arr;
3. 二维数组传参的本质
- 传参方式:二维数组可以通过数组指针或者数组名传递。
- 形参为数组:
void test(int a[3][5], int r, int c)
- 形参为指针:
void test(int (*p)[5], int r, int c)
- 解释:二维数组传递本质上是传递第一行的地址,数组名表示的是第一行的地址。
- 形参为数组:
4. 函数指针变量
-
定义:函数指针变量是用来存储函数地址的指针,可以通过该指针调用函数。
-
创建函数指针:
void (*pf)() = &test;
- 也可以省略
&
,直接使用函数名来赋值。
- 也可以省略
-
调用函数:
(*pf)();
- 或者直接使用
pf()
。
- 或者直接使用
-
函数指针的解析:
int (*pf3)(int, int)
表示pf3
是一个指向返回int
类型并接受两个int
类型参数的函数的指针。
5. 函数指针数组
- 定义:函数指针数组是一个数组,其中每个元素都是一个函数指针。
- 定义方法:
int (*parr1[3])();
- 例子:用函数指针数组实现计算器功能:
int (*p[5])(int, int) = {0, add, sub, mul, div};
6. 转移表
- 定义:转移表利用函数指针数组实现条件分支结构,例如计算器的实现。
- 例子:
int (*p[5])(int, int) = { 0, add, sub, mul, div };
- 通过用户输入选择对应的计算操作,调用相应的函数。
7. 回调函数
- 定义:回调函数是指通过函数指针传递并在需要时调用的函数。
- 例子:改造计算器,使用回调函数来简化代码:
void calc(int(*pf)(int, int)) { int ret = 0, x, y; printf("输入操作数:"); scanf("%d %d", &x, &y); ret = pf(x, y); printf("ret = %d\n", ret); }
9.qsort 函数模拟实现
为了模拟 qsort
函数的排序功能,可以使用回调函数和冒泡排序的方式。利用 void*
类型的指针,我们可以实现通用排序函数,支持排序不同类型的数据。
代码实现:
#include <stdio.h>
int int_cmp(const void *p1, const void *p2) {
return (*(int *)p1 - *(int *)p2); // 整数比较函数
}
void _swap(void *p1, void *p2, int size) {
int i;
for (i = 0; i < size; i++) {
char tmp = *((char *)p1 + i); // 逐字节交换数据
*((char *)p1 + i) = *((char *)p2 + i);
*((char *)p2 + i) = tmp;
}
}
void bubble(void *base, int count, int size, int (*cmp)(void *, void *)) {
int i, j;
for (i = 0; i < count - 1; i++) {
for (j = 0; j < count - i - 1; j++) {
if (cmp((char *)base + j * size, (char *)base + (j + 1) * size) > 0) {
_swap((char *)base + j * size, (char *)base + (j + 1) * size, size);
}
}
}
}
int main() {
int arr[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 0};
int i;
int arr_size = sizeof(arr) / sizeof(arr[0]);
bubble(arr, arr_size, sizeof(int), int_cmp); // 使用冒泡排序
// 输出排序后的结果
for (i = 0; i < arr_size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
代码解释:
-
int_cmp
函数:这是一个用于比较两个整数的函数,返回比较结果,适用于qsort
或者bubble
函数的回调。 -
_swap
函数:用于交换两个void*
类型指针指向的内存块的数据。它逐字节交换数据,确保通用性。 -
bubble
函数:实现冒泡排序的核心逻辑。它接受void*
类型的指针,可以排序任意类型的数据,比较函数和数据类型通过void*
指针传递。
输出示例:
0 1 2 3 4 5 6 7 8 9
10.typedef 关键字
typedef
关键字用于为已有的类型定义一个新的名字。这样可以提高代码的可读性,简化复杂类型的书写。typedef
可以用于基本数据类型、指针、数组、结构体等。
代码示例:
#include <stdio.h>
// 使用 typedef 创建类型别名
typedef unsigned int uint; // 将 unsigned int 重命名为 uint
typedef int* ptr_t; // 将 int* 重命名为 ptr_t
typedef void(*pfun_t)(int); // 将 void(*)(int) 函数指针类型重命名为 pfun_t
int main() {
uint a = 10; // uint 等同于 unsigned int
ptr_t p = &a; // ptr_t 等同于 int*
// 使用 typedef 定义的函数指针类型
pfun_t func = NULL;
// 输出 a 的值和 p 所指向的值
printf("a = %u, *p = %d\n", a, *p);
return 0;
}
代码解析:
-
typedef unsigned int uint;
将unsigned int
重命名为uint
。 -
typedef int* ptr_t;
将int*
重命名为ptr_t
,可以方便地表示指向int
类型的指针。 -
typedef void(*pfun_t)(int);
将void (*)(int)
函数指针类型重命名为pfun_t
,简化了函数指针的定义。