IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> ARM Study Day11:标准C之函数指针、高级指针、字符指针数组、动态分配内存、标准文件操作库函数 -> 正文阅读

[嵌入式]ARM Study Day11:标准C之函数指针、高级指针、字符指针数组、动态分配内存、标准文件操作库函数

在这里插入图片描述

//函数指针用法1演示
#include <stdio.h>
int add(int a, int b)	{
	return a + b;
}

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

int main(void)
{
	int ret = 0;
	//声明函数指针类型并且定义初始化函数指针变量pfunc,保存add函数的首地址
	int (*pfunc)(int, int) = add; //pfunc指向add
	//通过pfunc间接调用指向的add函数并且给add函数传递函数,用ret保存指向函数返回值
	ret = pfunc(100, 200);
	printf("add函数的返回值是%d\n", ret);
	//让pfunc保存sub函数的首地址指向sub函数
	pfunc = sub;
	//让pfunc间接调用指向的sub函数并且给sub函数传递参数
	ret = pfunc(100, 200);
	printf("add函数返回值是%d\n",  ret);
	return 0; 
}	

//函数指针用法2演示
#include <stdio.h>
//声明函数指针类型并且取别名
//给int (*)(int, int)类型取别名叫pfunc_t
typedef int (*pfunc_t)(int, int);
int add(int a, int b)   {
        return a + b;
}

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

int main(void)
{
        int ret = 0;
        //定义初始化函数指针变量pfunc,保存add函数的首地址
        pfunc_t pfunc  = add; //pfunc指向add
        //通过pfunc间接调用指向的add函数并且给add函数传递函数,用ret保存指向函数返回值
        ret = pfunc(100, 200);
        printf("add函数的返回值是%d\n", ret);
        //让pfunc保存sub函数的首地址指向sub函数
        pfunc = sub;
        //让pfunc间接调用指向的sub函数并且给sub函数传递参数
        ret = pfunc(100, 200);
        printf("add函数返回值是%d\n",  ret);
        return 0;
} 

```c
//定义回调函数:add和sub,回调函数的意思就是这些函数可以当成参数传递给别的函数调用
typedef int (*pfunc_t)(int, int);
int add(int a, int b)   {
        return a + b;
}

int sub(int a, int b){
        return a - b;
}
//定义调用函数cal:调用函数将来他的形参中有一个函数指针变量来保存回调函数的首地址
//那么将来调用函数通过形参函数指针变量可以间接调用回调函数

int cal(int a, int b, pfunc_t pfunc)
{
        if(pfunc == NULL)  //如果没有用给调用函数cal传递回调函数,那么就用cal函数默认的相乘功能
                return a * b;
        else
                return pfunc(a, b);//如果给cal函数传递了一个回调函数,那么就不用cal的默认相乘功能
                                        //那么就用回调函数想要的功能:相加或者相减
}
int main(void)
{
        printf("%d\n",cal(50, 100, NULL));   //就想用默认功能
        printf("%d\n",cal(50, 100, add));       //不想用默认功能,用加
        printf("%d\n",cal(50, 100, sub));       //不想用默认功能,用减
        return 0;
}


123
在这里插入图片描述

123


```c
//函数指针玩法
#include <stdio.h>
#include <stdlib.h>  //声明qsort函数
int intcmp(const void *p1, const void *p2)
{
        return *(const int *)p1 - *(const int *)p2;
}

int main(void)
{
        int a[] = {13, 34, 9, 44, 54, 22, 15, 9 };
        int len = sizeof(a)/sizeof(a[0]);
        //qsort已经把快速排序算法流程算好了,只需要编写一个回调函数intcmp
        //比较两个数的大小,然后将比较的结果给qsort,将来qsort自动调用intcmp,
        //根据返回值结果自动进行排序
        //大大减轻开发的工作量
        qsort(a, len, sizeof(a[0]), intcmp);
        for(int i = 0;i < len; i++)
                printf("%d\n", a[i]);
        printf("\n");
        return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1111

//数组指针演示
#include <stdio.h>
int main(void){
	int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
	for(int i = 0; i < sizeof(a)/sizeof(a[0]); i++)	
	{
		for(int j = 0; j< sizeof(a[0])/sizeof(a[0][1]); j++)
			printf("%d ", a[i][j]);  //*(a[i]+j) = *(*(a+i)+j)
		printf("\n");
	}
	//通过数组指针来访问二维数组
	int (*p)[4] = a;//定义初始化数组指针变量p来保存二维数组的首地址
	for(int i = 0; i< 3; i++){
		for(int j = 0; j < 4; j++)
			printf("%d ", p[i][j]);
		printf("\n");
	}
       //二维转一维	
	int *p1 =(int *)a;
	for(int i = 0; i < 12; i++)
		printf("%d ", p1[i]);
	printf("\n");

	//一维转二维
	int b[] = {0,1,2,3,4,5,6,7,8,9,10,11};
	int (*p2)[4] =(int (*)[4])b; //强制将int类型转换为数组指针
	for(int i = 0; i < 3; i++)
		for(int j = 0; j < 4; j++)
			printf("%d ", a[i][j]);
		printf("\n");
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//二级指针演示
#include <stdio.h>
int main(void) {
        int n = 10;
        int *p = &n;
        int **pp = &p;
        printf("n = %d, &n = %p\n, n, &n");
        printf("p = %p, &p = %p, *p = %d\n", p, &p, *p);
        printf("pp = %p, &pp = %p, *pp = %p, **pp = %d\n", pp, &pp, *pp, **pp);
        //通过p访问n
        *p = 300;
        printf("n = %d\n", *p);
        //通过pp访问n
        **pp = 400;
        printf("n = %d\n", **pp);
        return 0;
}

1111

//二级指针的应用
//笔试题:编写一个函数实现两个字符串的交换
//char *pa = "hello", char *pb = "world"  目标:pa->"world" pb->"hello"
//切记切记切记:如果将来一个函数 要修改一级指针的指向,这个函数的形参要定义为二级指针
#include <stdio.h>
void swap(char *p1, char *p2){ //p1 = pa, p2=pb
        char *p3 = p1;
        p1 = p2;
        p2 = p3;
}

void swap1(char **p1, char **p2){//p1 = &pa p2 =&pb
        char *p3 = *p1; //将pa保存的地址给p3
        *p1 = *p2;  //直接将实参pb保存的地址给实参pa
        *p2 = p3;  //将p3保存的地址直接给实参pb
}
int main(void)
{
        char *pa = "hello", *pb = "world";
        swap(pa, pb);
        printf("pa = %s, pb = %s\n",pa, pb);
        swap1(&pa, &pb);
        printf("pa = %s, pb = %s\n",pa, pb);
        return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


//malloc /free 标准C库函数演示:从堆区分配内存,C语言的第四种分配内存方法,可以大量分配并且类型无关
//分配内存的效率低下
#include <stdio.h>
#include <stdlib.h>  //库函数的声明
int main(void){
        int *p = NULL;
        //调用malloc分配内存
        p = (int *)malloc(8); //连续分配8字节内存,返回内存的首地址保存到p中
        if(p == NULL)
        {
                printf("内存分配失败了。\n");
                return -1;
        }
        printf("分配成功,首地址是%p\n", p);
        *(p+0) = 520;  //向前4字节写入520
        *(p+1) = 521;  //向后4字节写入520
        printf("%d, %d\n", p[0], p[1]);
        //调用free释放内存否则内存泄漏
        free(p);
        p= NULL;        //好习惯,否则p是一个野指针,因为p此时指向的内存已经被释放了,不再是合法有效的内存了
        return 0;
}

//calloc/free标准C库函数演示:从堆区分配额你村,C语言的第四种分配内存方法:可以大量分配并且类型无关
//分配内存的效率低下
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
	int *p = NULL;
	//调用calloc分配内存
	p = (int *)calloc(4, sizeof(int));//连续分配16字节内存,返回内存的首地址保存到P中
	if(p == NULL){
	printf("内存分配失败了.\n");
	return -1;
}
	printf("分配成功,首地址是%p\n", p);
	//初始化分配的内存
	for(int i = 0; i < 4; i++)
		p[i] = i + 1;
	//打印
	for(int i = 0; i < 4; i++)
		printf("%d", *(p+i));
	printf("\n");
	//调用free释放内存 否则内存泄漏
	free(p);
	p = NULL;
	return 0}

//分配内存的效率低下
#include <stdio.h>
#include <stdlib.h>
#define NUMB 4
int main(void)
{
        int *p = NULL;
        //调用malloc分配内存        p = (int *)malloc(8);//连续分配8字节内存,返回内存的首地址保存到P中
        if(p == NULL){
        printf("内存分配失败了.\n");
        return -1;
}
        printf("分配成功,首地址是%p\n", p);
        *(p + 0) = 520;
        *(p + 1) = 521;
        printf("%d, %d\n", p[0], p[1]);
        //调用realloc调整内存大小
        p = realloc(p, 16);
        //在原先malloc分配的内存基础上继续额外多分配8字节内存,并且返回新的内存
首地址给p
        //初始化分配的内存
        for(int i = 0; i < NUMB; i++)
                p[i] = i + 1;
        //打印
        for(int i = 0; i < NUMB; i++)
                printf("%d ", *(p+i));
        printf("\n");
        //调用free释放内存 否则内存泄漏
        free(p);
        p = NULL;
        //好习惯,否则p是一个野指针
        return 0}

在这里插入图片描述

**

IO流与标准库

**
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//文件操作标准C库函数
#include <stdio.h>
int main(void)
{
        FILE *fp = NULL;

        fp = fopen("a.txt", "r");
        if(fp == NULL){
                printf("打开失败.\n");
                return -1;
        }

        printf("打开成功.\n");

        fclose(fp);
        return 0;
}

//文件操作标准C库函数
#include <stdio.h>
int main(void)
{
        FILE *fp = NULL; //FILE结构体就是描述文件打开后的各种属性,程序员无需关注内部成员
        fp = fopen("a.txt", "r");//以只读方式打开当前目录下的a.txt文件
        if(fp == NULL){
                printf("打开失败.\n");
                return -1;
        }
        printf("打开成功.\n");
        int i = 0;
        char a[20] = {0};
        double d = 0;
        //按照指定的格式从fp对应的文件中读取数据存到变量i,a,d中
        fscanf(fp, "%d%s%lf", &i, a, &d);
        fclose(fp); //关闭文件
        fp = NULL; //好习惯
        printf("i = %d, a = %s, d = %lg\n", i, a, d);
        FILE *fpw = fopen("b.txt", "w");
        if(fpw == NULL)
        {
                printf("打开失败。\n");
                return -1;
        }
        fprintf(fpw, "copy:%d %s %lf", i, a, d);
        fclose(fpw); //关闭b.txt
        fpw = NULL;
        //stdin,stdout,stderr三个默认的文件指针
        fscanf(stdin, "%d%s%lf", &i, a, &d);//从键盘标准输入设备上输入数据保存到变量中
        printf("i = %d, a = %s, d = %lg\n", i, a, d);
        fprintf(stdout, "i = %d, a = %s, d = %lg\n", i, a, d);
        fprintf(stderr, "i = %d, a = %s, d = %lg\n", i, a, d);
        return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//fputc和fget函数展示
#include <stdio.h>
int main(void)
{
        FILE *fpr = fopen("a.txt", "r");
        FILE *fpw = fopen("b.txt", "w+");
        char str[4] = {0};  //用于保存从文件中读取的字符串
        while(fgets(str, 4, fpr) != NULL)  //循环从文件中读取3个字符
        {
                fputs(str, fpw); //然后将读取的数据写入到文件中
        }
        while(1)
        {
                ch = fgetc(fpr); //从a.txt读取一个字符
                if(ch == EOF)   //判断是否读取到文件的尾部
                        break;
                fputc(ch, fpw);  //向b.txt写入一个字符
        }
        fclose(fpr);
        fclose(fpw);
        fpr = NULL;
        fpw = NULL;
        return 0;
}

在这里插入图片描述
在这里插入图片描述

//fread,fwrite
#include <stdio.h>
int main(void){
        FILE *fp = fopen("a.txt", "w+");
        int a[] = {1,2,3,4,5,6,7,8};
        int len = sizeof(a)/sizeof(a[0]);
        int size = 0;

        size = fwrite(a, sizeof(int), len, fp);//向文件写入len个int>类型的数据,期望写入4*len=32个字节
        printf("实际写入了%d个数据\n", size);

        rewind(fp);  //将文件的操作位置重新定位到文件的开头

        int b[8] = {0}; //暂存将来从文件中读取到的数据
        size = fread(b, sizeof(int), 10, fp);//从文件中希望读取10个>数据
        printf("实际读取了%d个数据\n", size);

        for(int i = 0;i < size; i++)
                printf("%d", b[i]);
        printf("\n");

        fclose(fp);
        fp = NULL;
        return 0;
}

在这里插入图片描述

//fread,fwrite
#include <stdio.h>
int main(void){
	FILE *fp = fopen("a.txt", "w+");
	int a[] = {1,2,3,4,5,6,7,8};
	int len = sizeof(a)/sizeof(a[0]);
	int size = 0;

	size = fwrite(a, sizeof(int), len, fp);//向文件写入len个int类型的数据,期望写入4*len=32个字节
	printf("实际写入了%d个数据\n", size);

	rewind(fp);  //将文件的操作位置重新定位到文件的开头

	int b[8] = {0}; //暂存将来从文件中读取到的数据
	size = fread(b, sizeof(int), 10, fp);//从文件中希望读取10个数据
	printf("实际读取了%d个数据\n", size);

	for(int i = 0;i < size; i++)
		printf("%d", b[i]);
	printf("\n");

	//fseek函数演示
	int c[2] = {0};
	fseek(fp, 8, SEEK_SET);
	//1 2 3 4 5 6 7 8
	//
	fread(c, sizeof(int), 2, fp);//读取完毕,文件位置跑到5
	printf("%d %d\n",c[0], c[1]);

	fseek(fp, 8, SEEK_CUR);//从当前位置(5)个位置往后8个字节开始操作文件
	//1 2 3 4 5 6 7 8
	//
	fread(c, sizeof(int), 2, fp);//读取完毕,文件位置跑到5
	printf("%d %d\n",c[0], c[1]);

	fseek(fp, -12, SEEK_END); //从文件微博往前12个字节开始操作文件
	//1 2 3 4 5 6 7 8
	//
	fread(c, sizeof(int), 2, fp);//读取完毕,文件位置跑到5
	printf("%d %d\n",c[0], c[1]);
	fclose(fp);
	fp = NULL;
	return 0;
}

在这里插入图片描述
在这里插入图片描述

//feof,ferror
#include <stdio.h>
int main(void)
{
	FILE *src = fopen("a.txt", "r");
	FILE *dst = fopen("b.txt", "w");
	int bytes;
	unsigned char buf[1024];

	while(bytes = fread(buf, 1, sizeof(buf), src)){
		if(fwrite(buf, 1, bytes, dst) != bytes)
		{
			printf("写入失败。\n");
			return -1;
		}
	}

	//判断读取失败的原因
	//读失败
	if(ferror(src)){
		printf("读取失败。\n");
	}

	//读到尾部
	if(feof(src))
	{
		printf("到头啦\n");
		return 0;
	}

	fclose(src);
	fclose(dst);
}

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 22:22:07  更:2022-03-17 22:23:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:36:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码