函数指针笔记

int main() {
	int arr1[10] = {0};
	int(*p1)[10] = &arr1;// p1存放的是数组的地址,该数组有10个int空间
	int* arr2[10] = {nullptr};   // p2存放的是int指针
	for (int i = 0; i < 10; i++) {
		(*p1)[i] = i * 10;
	}
	for (int num : (*p1)) {
		printf("%d\n", num);
	}
	int* (*p2)[10] = &arr2; // p2存放的是数组的地址,数组存放的是10个int指针

	return 0;
}
int add_int(int a, int b) {
	return a + b;
}

int sub_int(int a, int b) {
	return a - b;
}

int main() {
	int a = 10;
	int b = 20;
	int c = 0;
	
	int (*p_fun)(int, int) = nullptr;//指向函数的指针,同参数,同返回值即可指向
	p_fun = &add_int;          //同p_fun = &add_int;
	c = (*p_fun)(a, b);        //旧的调用方法
	c = p_fun(a, b);           // 新的调用方法,不直观


	p_fun = &sub_int;//同p_fun = sub_int;

	return 0;
}
int main() {
	int a = 10;
	int b = 20;
	int c = 0;

	int (*p_fun)(int, int) = nullptr;
	p_fun = &add_int;

	//p_arr1是数组,数组有两个元素,每个元素都是指针,每个指针存放一个函数的地址
	int (*p_arr1[2])(int, int) = { &add_int, &sub_int };

	// p_arr1[0] = p_fun;
	for (int i = 0; i < 2; i++) {
		c = (*p_arr1[i])(a, b);//p_arr1[i](a, b)
		printf("%d\n", c);
	}

	//p_arr2是数组,数组有两个元素,每个元素都是指针,每个指针存放一个函数的地址
	int* (*p_arr2[2])(int, int);

	return 0;
}

函数指针和基本数据类型指针的区别

int main() {
	int a = 10;
	int b = 20;
	int c = 0;

	int (*p_fun)(int, int) = nullptr;

	//p_arr1是数组,数组有两个元素,每个元素都是指针,每个指针存放一个函数的地址
	int (*p_arr1[2])(int, int) = { &add_int, &sub_int };

	p_fun = p_arr1[0];
	sizeof(p_fun);//4
	sizeof(*p_fun);//无法计算
	p_fun++; // 函数指针不可自增,因为函数大小无法计算,不能通过计算指向下一个函数
	return 0;
}

回调函数调用方式

void test1(int a, int b, int(*p_fun)(int, int)) {
	if (p_fun != nullptr) {
		int c = (*p_fun)(a, b);
		printf("%d\n", c);
	}
}

//编译器自动将形参的函数声明转换成函数指针
void test2(int a, int b, int p_fun (int, int)) {
	if (p_fun != nullptr) {
		int c = (*p_fun)(a, b);
		printf("%d\n", c);
	}
}

int main() {
	int a = 10;
	int b = 20;
	test1(a, b, &add_int);
	test2(a, b, &sub_int);
	return 0;
}

在这里插入图片描述

利用回调函数打印不同类型数组

struct Student {
	char name[16];
	int age;
};

void* print_int(void* p) {
	// 把指针p强转
	const int* tmp = (const int*)p;
	printf("%d ", *tmp);
	return (void*)(tmp + 1);
}

void* print_double(void* p) {
	// 把指针p强转
	const double* tmp = (const double*)p;
	printf("%f ", *tmp);
	return (void*)(tmp + 1);
}

void* print_stu(void* p) {
	// 把指针p强转
	const struct Student* tmp = (const struct Student*)p;
	printf("%s %d\n", tmp->name, tmp->age);
	return (void*)(tmp + 1);
}

// 这里用void*是因为不确定参数的类型
void print_arr(void* arr, int len, void* (*p_fun)(void*)) {
	void* tmp = arr;
	for (int i = 0; i < len; i++) {
		//这里tmp一直在往后移动(print_int中体现)
		tmp = p_fun(tmp);
	}
	printf("\n");
}

int main() {
	int arr1[] = { 4, 4213, 54, 1245, 1, 45, 2 };
	int len1 = sizeof(arr1) / sizeof(arr1[0]);

	double arr2[] = { 134.1, 42.42, 4132.42, 12.543 };
	int len2 = sizeof(arr2) / sizeof(arr2[0]);

	struct Student arr3[] = { {"shen",20},{"chen",18},{"zhang",19} };
	int len3 = sizeof(arr3) / sizeof(arr3[0]);

	print_arr(arr1, len1, print_int);
	print_arr(arr2, len2, print_double);
	print_arr(arr3, len3, print_stu);
	return 0;
}

在这里插入图片描述
通过q_sort排序理解void*以及仿函数

// 这里传入的是指向char*类型的指针(即char**)
int cmp_str(const void* p1, const void* p2) {
	const char* str1 = *(const char* *)(p1);
	const char* str2 = *(const char* *)(p2);
	/*int len1 = sizeof(str1) / sizeof(str1[0]);
	int len2 = sizeof(str2) / sizeof(str2[0]);
	int len = len1 < len2 ? len1 : len2;
	for (int i = 0; i < len; i++) {
		if (str1[i] != str2[i]) {
			return str1[i] - str2[i];
		}
	}*/
	if (strcmp(str1, str2) < 0) {
		return -1;
	}
	else if(strcmp(str1, str2) > 0){
		return 1;
	}
	return 0;
}

// 这里传入的是指向int*类型的指针
int cmp_int(const void* p1, const void* p2) {
	int num1 = *(const int*)p1;
	int num2 = *(const int*)p2;
	if (num1 < num2) {
		return -1;
	}
	else if(num1 > num2){
		return 1;
	}
	else {
		return 0;
	}
}

int cmp_stu_age(const void* p1, const void* p2) {
	const struct Student* stu_p1 = (const struct Student*)p1;
	const struct Student* stu_p2 = (const struct Student*)p2;
	if (stu_p1->age > stu_p2->age) {
		return 1;
	}
	else if (stu_p1->age < stu_p2->age) {
		return -1;
	}
	else {
		return 0;
	}
}

int cmp_stu_name(const void* p1, const void* p2) {
	const struct Student* stu_p1 = (const struct Student*)p1;
	const struct Student* stu_p2 = (const struct Student*)p2;
	if (strcmp(stu_p1->name, stu_p2->name) > 0) {
		return 1;
	}
	else if (strcmp(stu_p1->name, stu_p2->name) < 0) {
		return -1;
	}
	else {
		return 0;
	}
}

int main() {
	int arr[] = { 4,1,63,561,35,6357,6,87 };
	int len1 = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, len1, sizeof(int), cmp_int);
	for (int num : arr) {
		printf("%d ", num);
	}
	printf("\n");

	// 字符串存放在数据区,不可改变
	const char* str[] = {
		"rqew","ffs","bcvn","vxbz",
		"rewf","fdsa","bav","vsag"
	};
	int len2 = sizeof(str) / sizeof(str[0]);
	qsort(str, len2, sizeof(char*), cmp_str);
	for (const char* s : str) {
		printf("%s\n", s);
	}

	struct Student arr3[] = { {"shen",20},{"chen",18},{"zhang",19} };
	int len3 = sizeof(arr3) / sizeof(arr3[0]);
	qsort(arr3, len3, sizeof(struct Student), cmp_stu_age);
	for (struct Student stu : arr3) {
		printf("%s %d\n", stu.name, stu.age);
	}
	qsort(arr3, len3, sizeof(struct Student), cmp_stu_name);
	for (struct Student stu : arr3) {
		printf("%s %d\n", stu.name, stu.age);
	}
}

关于命令行参数

// argv是一个数组,元素是char*,0号元素为应用程序名,剩余元素为命令行参数
// argc表示参数数量(包括应用程序名)
int main(int argc, char* argv[], char* env[]){
    for (int i = 0; i < argc; i++) {
        printf("%s\n", argv[i]);
    }

    argv[0][1] = '3'; // 可以改动,数据不在数据区,而在栈区
    printf("%s\n", argv[0]);

    for (int i = 0; env[i] != nullptr; i++) {
        printf("%s\n", env[i]); // 打印系统环境变量
    }
}

在这里插入图片描述

复制文件的程序

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

int main(int argc, char* argv[]) {
	if (argc < 3) {
		printf("命令行参数不匹配!");
		return 1;
	}
	//argv[0] = 3.exe,argv[1]=src.txt,argv[2]=dst.txt
	FILE* fp_read = nullptr;
	FILE* fp_write = nullptr;
	errno_t read_flag = fopen_s(&fp_read, argv[1], "rb");
	errno_t write_flag = fopen_s(&fp_write, argv[2], "wb");
	if (fp_read == nullptr) {
		printf("open file %s error : %d\n", argv[1], read_flag);
		exit(1);
	}
	if (fp_write == nullptr) {
		printf("open file %s error : %d\n", argv[2], write_flag);
		exit(1);
	}
	// fp_read移动到文件末尾,从SEEK_END偏移0
	fseek(fp_read, 0, SEEK_END);
	//src文件大小,字节个数
	int len = ftell(fp_read);
	// fp_read移动到文件首
	rewind(fp_read);// 等价于fseek(fp_read, 0, SEEK_SET);
	printf("%s 长度: %d字节\n",argv[1], len);

	if (len > 0) {
		char* buff = (char*)malloc(sizeof(char) * (len+1));
		fread(buff, sizeof(char), len, fp_read);
		fwrite(buff, sizeof(char), len, fp_write);
		printf("文件拷贝成功!");
	}


	fclose(fp_read);
	fp_read = nullptr;
	fclose(fp_write);
	fp_write = nullptr;

	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bugcoder-9905

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值