高级C语言教程-存储器和指针
ATPCS即ARM-THUMB procedure call standard(ARM-Thumb过程调用标准)的简称
回调函数
通常情况下函数的调用是用户的函数调用操作系统的函数,上层的函数调用底层的函数,而所谓的回调是是指操作系统来调用用户编写的函数,或者底层的函数调用上层的函数。
由于操作系统的代码在用户代码之前就已经完成编译,因此操作系统发起的回调一般由用户编写的函数的函数指针传递给操作系统再由操作系统实现回调。
正如嵌入式的函数的中断等事件的函入口就是采用的回调函数的机制。
多线程
将函数的指针传进负责建立多线程的API中。在一个任务系统中,每个任务从本质上来讲可以理解为是一个拥有自己独立堆栈的函数,在用户需要创建一个新的任务或线程的时候,需要调用由操作系统提供的API 函数(系统调用)。
在函数中实现讲一个数值转换为字符串,相当于sprintf的使用,但是经常使用自己定义的函数当然能够加强自己对于语言的进一步的了解,并且久而久之就自己能够熟练的写出一首很好的代码。
//UnsToStr -- 将一个无符号值转换为字符串
void UnsToStr(unsigned u,char *str)
{char *sreStart = str;do*str++ = (u % 10) + '0';while((u/=10)>0);*str = '\0'; //在结束的时候加上这样才能使用的字符串确认结尾否则将不是一个完整的字符串RenerseStr(strStart);
}
//C语言标准库函数strcpy的一种典型的工业级的最简实现。
//返回值:目标串的地址。
//对于出现异常的情况ANSI-C99标准并未定义,故由实现者决定返回值,通常为NULL。
//参数:des为目标字符串,source为原字符串。
char* strcpy(char* des,const char* source){char* r=des;assert((des != NULL) && (source != NULL));while((*r++ = *source++)!='\0');return des;}
//while((*des++=*source++));的解释:赋值表达式返回左操作数,所以在赋值'\0'后,循环停止。
⒈strcpy的实现代码char * strcpy(char * strDest,const char * strSrc){if ((NULL==strDest) || (NULL==strSrc)) //[1]throw "Invalid argument(s)"; //[2]char * strDestCopy = strDest; //[3]while ((*strDest++=*strSrc++)!='\0'); //[4]return strDestCopy;
}
利用堆栈保存函数调用的返回地址(对于中断处理程序还包括程序状态字寄存器)
大家都知道堆栈的这个功能,当函数调用或者中断发生的时候,返回的地址会自动的压入当前堆栈中(对于ARM处理器而言,这个过程不是由硬件自动完成的,硬件只负责将返回地址保存到相应的链接寄存器r14中去)由编译器插入的代码完成压栈工作)。当程序执行流程需要返回的时候,通过调用相应的返回指令(ARM处理器没有专门的返回指令,只能通过其他指令完成)将堆栈中保存的返回地址弹出到PC中
利用堆栈保存在被调函数中需要使用的寄存器值
当程序的控制权进入到被调函数(Callee)后,被调函数的代码函数的代码可能需要用到一些寄存器作为数据暂存,但是这些寄存器可能已经被(Caller)函数(调用函数)使用,为了满足Callee的需求,而不至于损坏Caller中已经使用的数据,编译器会在callee函数开始使用这些寄存器之前,将这些寄存器中的原有数据压入到堆栈保存,在Callee返回Caller之前,编译器还需要插入一段代码将这些保存在堆栈中的数据恢复(通过退栈操作)到相关的寄存器中去;
在实际的C程序中,编译器会根据需要插入维护这些功能的代码,因此在函数调用的时候,编译器会维护一个与调用相关的栈结构,通常我们将这个栈结构称为调用栈帧(Call Stack Frame);
函数的返回值通常保存在r0中。
正如大多数管理资源分配的算法一样,我们将在系统堆栈中构建空闲链表,每次的分配其实就是遍历整个空闲链表的各个空闲区域,如果某个空闲区域的大小能够满足用户申请的大小,系统将在高地址切一块分出来,,动态内存的释放就是动态申请的逆过程,释放函数首先将遍历整个空闲链表,寻找合适的位置将用户释放的内存块释放到空闲链表中去。
贵有恒,何必三更眠五更起;最无益,只怕一日曝十日寒!
高级C语言教程-存储器和指针相关推荐
- 单片机c语言指针作用,单片机C语言教程:C51指针的使用
指针就是指变量或数据所在的存储区地址.如一个字符型的变量 STR 存放在内存单元DATA 区的 51H 这个地址中,那么 DATA 区的 51H 地址就是变量 STR 的指针.在 C 语言中指针是一个 ...
- 高级C语言教程-指针和存储
讲一讲C语言中的值传递引用还有地址传递: 以下面的一段代码为例: void GetMemory(char *p) {p = (char *) malloc(100); } void Test(void ...
- 高级C语言教程-关键字和运算符
volatile 关键字 一个定义为volatile的变量会被意想不到的改变,这样编译器就不会假设这个变量的值了,精确的来说就是编译器在用到这个变量的时候必须每次都小心的重新读取这个变量的值,而不是使 ...
- 高级C语言教程-编译链接调试
编译器 一般认为所谓的编译就是将便于程序员编写.阅读.维护的高级计算机语言翻译为计算机能够解读.运行的低级机器语言的特定程序.编译器将源代码作为输入翻译生成使用目标语言的等价程序,事实上一般的C语言程 ...
- 51单片机指针c语言,单片机C语言教程:C51指针的使用
#include //预处理文件里面定义了特殊寄存器的名称如 P1 口定义为 P1 void main(void) { //定义花样数据,数据存放在片内 CODE 区中 unsigned char c ...
- 高级C语言教程-作用域
C语言中一共有4中作用域:代码块作用域.文件作用域.函数作用域和原型作用域. 1.代码块的作用域,位域一对大括号中的所有语句构成一个代码块(Block)任何在代码块开始声明的标识符都具有代码块作用域, ...
- 高级C语言教程-C语言函数setjmp()函数
**与刺激的abort()和exit()相比,goto语句看起来是处理异常的更可行方案.不幸的是,goto是本地的: 它只能跳到所在函数内部的标号上,而不能将控制权转移到所在程序的任意地点(当然,除非 ...
- 高级C语言教程-sscanf()函数使用方式
C语言支持可变参数的函数,这需要采用 #include <stdio.h>int main( void ) {char tokenstring[] = "15 12 14...& ...
- 高级C语言教程编码风格
列表内容 每个C文件包含额头文件的顺序应该遵循先底层后上层的原则, ASIC-ii头文件 底层库头文件 操作系统头文件 应用程序头文件 2.利用括号来表示运算的优先顺序 每行语句单独一行,不要使用过长 ...
最新文章
- 用python写希尔排序_python希尔排序介绍(实例)
- [文档].JLINK挂了怎么办?自己修![转载].JLINK_V8固件烧录和固件升级指导.pdf
- rpm安装mysql报错NOKEY_rpm包安装报错: Header V3 RSASHA256 Signature, key ID fd431d51 NOKEY
- 【深度学习】基于Pytorch多层感知机的高级API实现和注意力机制(二)
- Android学习笔记之自定义Toast
- STM32F103的11个定时器详解
- 计算方法之迭代法求方程根
- centos 6.2 vnc
- Python爬取豆瓣电影
- vue点击后html放大,vue实现点击图片放大效果
- MATLAB离散控制系统
- 美国国家安全局(NSA)网络攻击主战武器“验证器”
- 今天你的人生做减法了吗?
- 6-2 折半查找的实现 (10 分)
- 小学生四则运算考试系统Java
- 比较好的刷题网站推荐
- IDEA设置背景和定时更换背景
- java基于ssm+vue+elementUI在线影评电影评论投票系统
- 思科前员工为报复恶意删除400多台虚拟机,公司损失超1600万
- Git最详细的基础教程