- 浏览: 208447 次
- 性别:
- 来自: 重庆
-
文章分类
最新评论
原文 : http://blog.csdn.net/fanwei326/article/details/6127091
东莞权智集团 范伟
mail: fanwei326@163.com; wfan@gsl.com.cn
本文若有错误之处,欢迎来信指正。
uC/OS-II内存管理函数内最难理解的部分就是二维指针,本文以图文并茂的方式对二维指针进行了详细分析与讲解。看完本文,相信对C里面指针的概念又会有进一步的认识。
一、OSMemCreate( ) 函数中有如下语句:
OS_MEM *pmem;
INT8U *pblk;
void **plink;
INT32U i;
plink = (void **)addr; //指向所申请内存分区的起始地址
pblk = (INT8U *)addr + blksize; //所申请内存的第二个Block的起始地址
for (i = 0; i < (nblks - 1); i++) //依次申请nblks个Block,链接成单向链表
{
*plink = (void *)pblk;
plink = *plink;
pblk = pblk + blksize;
}
红色部分是初学者对本函数最难理解的部分,因为其用到了二维指针。二维指针就是指向指针的指针,他的内容是一个目标变量的地址,也就是说仍然是一个指针,对二维指针取两次内容才能取到目标变量的内容。这里先复习一下指针的知识:
int a = 5;
int *ptr;
ptr=&a; //ptr指针是地址,指向变量a所在地址。
则可以得出:
*ptr=a; //即指针ptr指向变量a所在地址,*ptr的值就是a的值5
由此类推,对于二维指针变量**plink,指针plink是地址,*plink是plink所指向的地址内的数据,不过同时这个数据也是一个指针,并且**plink是指针(*plink)所指向的地址内的数据。
一维指针所指向的地址内存放的是普通数据,如上述ptr指针所指向的地址内存放的是int型数据5。
二维指针所指向的地址内存放的是一个一维指针,如上述指针plink所指向的地址内存放的是指针*plink。
下面详细分析上述OSMemCreate函数内的语句:
1、plink = (void **)addr;
addr本来是一个一维指针,指向所申请内存分区的起始地址。本句将addr强制转换为二维指针(注意经过强制转换后addr指针本身指向的地址是没有变化的),并将addr地址值赋给plink。则plink的内存中存储的是addr的值,即plink也指向addr所指向的分区起始地址,并且这个地址内存放的内容是指针(*plink),但指针(*plink)还未指向具体的地址。在这条语句之前,这个起始地址内的数据内容是未知的(由编译器分配的)。内存分区结构见下图1所示(假设申请的内存区有4个Block)。
在这个函数当中,我们想把addr指向的二维数组,分割成大小相同的若干块,并用指针把它们链接起来,链接指针放在每个block的首地址。但由于addr是一维指针,它指向的内容不会被解释成一个地址,而是一般的内容。我们要在这些block的首地址内存放指针,所以将addr强制转换成二维指针的目的就是让编译器将addr指向的内容解释成地址,也就是一个指针。
再将addr赋值给plink(让plink去执行连接的操作),使plink与addr指向同一个地址。*plink就是取plink与addr指向地址单元的内容,而这个内容是一个指针,也就是在以前addr指向的地方放上指针*plink。
2、pblk = (INT8U *)addr + blksize;
让pblk指向所申请内存的第二个Block的起始地址,见下图2所示。
因为addr是void型的,要强制转换为INT8U型。
3、*plink = (void *)pblk; //实际上是*plink = pblk,因为pblk是INT8U型的,要强制转换为void型
在for循环内对二维指针plink执行取内容操作(其内容为指针), *plink也是一个指针了(plink指针所代表的地址的内容),将下一个block的首地址赋值给*plink,使它指向的地方改为下一个blcok开始的地址处。
起始地址内的指针*plink被赋值为pblk,所以*plink与pblk一样指向下一个blcok开始的地址处。
如图3所示。
第一个block首地址内的内容为一个指针,该指针指向下一个block首地址。这个地址内存放的就是*plink的内容**plink。
只不过我们并不需要用到这个**plink。
4、plink = (void **)pblk;
功能与plink = (void **)addr 相似,即plink也指向第二个block的起始地址,并且使这个地址内存放的是指针(*plink)。
注意:因为plink所指向的地址变了,此时pblk所指向的地址
内的内容由原来的**plink变为了*plink指针。
并且 *plink还未被赋值,则**plink值是未知的
5、pblk = pblk + blksize;
pblk不断的下移,以指向再下一个block的开始处。
pblk(new)= pblk(old)+blksize
当再次进行for循环时,重复上述过程,利用每个block首地址内的指针将每个Block链接起来组成空闲块链表。
同样,*plink被赋值后,指向pblk所指向的地址,则该地址的
内容为**plink,只不过我们并不需要取出**plink。
6、pmem->OSMemFreeList = addr; /*pmem->OSMemFreeList指向空闲块链表第一个block首地址
在完成for循环后,使pmem->OSMemFreeList指向addr,组成完整的空闲块链表。
总结:进行(void**)强制转换的目的其实就是为了把所指向的地址的内容转换成一个指针。
二、在OSMemGet( )函数内同样有一条强制转换为二维指针的指令:
void *pblk;
执行操作:pmem->OSMemFreeList =*(void **)pblk;
pblk被强制转换为二维指针,然后取出其内容*pblk,也就是pblk地址内存放的链接指针。
意味着取出pblk的内容,由于pblk被强制转换成了二维指针,所以它的内容就不是一般的值,而是一个指针(这个指针指向下一个Block首地址)。
三、在INT8U OSMemPut (OS_MEM *pmem, void *pblk) 函数内同样有类似的指令:
① *(void **)pblk = pmem->OSMemFreeList; // 将欲释放的块添加到空闲块链表最前面
② pmem->OSMemFreeList = pblk;
首先要明白pmem->OSMemFreeList是指向空闲块链表第一个block的首地址的。
语句①将pblk强制转换为二维指针后,再将pmem->OSMemFreeList赋值给pblk的内容(*pblk指针)。根据OSMemPut函数的定义,pblk是函数的形参,是欲释放的块的首地址。所以也就是将pmem->OSMemFreeList指针放入欲释放的块的首地址内,此处强制转换为二维指针的目的就是让欲释放的块的首地址内能存放指针。则这个块的首地址内的指针就是指向原先空闲块链表第一个Block的首地址的,也就是说这个块变成了空闲块链表第一个Block,实现了将释放的块添加到空闲块链表最前面的目的。
然后语句②更新pmem->OSMemFreeList指针,使其指向新释放的块的首地址,这样就保证了pmem->OSMemFreeList始终指向空闲块链表第一个Block首地址。
发表评论
-
C++的原子操作
2012-12-20 17:43 4696在多进程(线程)访问资源时,能够确保所有其他的进程(线程 ... -
匿名namespace的作用以及它与static的区别
2012-12-20 17:24 1863一。匿名namespace的作用 在C语言中,如果我们 ... -
C++类型萃取技术
2012-12-19 15:16 1156Traits技术可以用来获得一个 类型 的相关信息的。 ... -
数值压缩存储方法Varint
2012-12-19 14:35 880转自:http://www.cnblogs.com/smark ... -
TypeList
2012-12-19 13:49 1162转自:http://blog.csdn.n ... -
template <unsigned int N>
2012-12-19 11:51 1508详见:http://stackoverflow.com/ ... -
多级指针和链表
2012-12-18 22:28 0如果看到一个声明:t ... -
理解*(void**)b
2012-12-18 22:03 0#include <stdio.h> ... -
STL标准库:Allocator能做什么
2012-12-18 20:10 0The Standard Librarian: Wha ... -
三种的allocator实现源代码的对比
2012-12-18 19:55 1352转自:http://blog.csdn.net ... -
结构体内变量相对便宜与list_entry()宏
2012-12-18 17:59 962#define list_entry(ptr, t ... -
声明与函数、函数指针---(*(void (*)( ) )0)( ) 解析
2012-12-18 17:33 1122概述 在很 ... -
c++模板(类型依赖)说明例子
2012-12-18 16:57 1171#include <iostream> # ... -
C++中三种new的用法
2012-12-18 16:44 1843我评价自己的C++水平还未入门的确不够准确,应该是远远未 ... -
C++,永久改变你写异常安全代码的方式(神奇的Loki::ScopeGuard)
2012-12-17 20:19 2527作者:Andrei Alexandrescu and P ... -
C++的make_pair函数
2012-12-17 17:19 3536Pairs C++标准程序库中凡是“必须返回两 ... -
C++的explicit构造函数
2012-12-13 15:59 683按照默认规定,只有一个参数的构造函数也定义了一个隐式转换 ...
相关推荐
根据提供的文件信息,我们可以深入探讨以下几个关键的知识点: ...总之,这段代码提供了一个很好的学习案例,不仅可以帮助初学者了解µC/OS-II的工作原理,还可以让他们通过实践加深对实时操作系统理论知识的理解。
本篇论文介绍了一种基于STM32微控制器和uC/OS-II实时操作系统的二维数控X-Y工作台控制系统的设计。STM32是STMicroelectronics生产的一款广泛应用于嵌入式应用的ARM Cortex-M系列微控制器。uC/OS-II是一个由Jean J. ...
内存控制块包含了关于内存分区和内存块的信息,如块的大小、状态(空闲或已分配)、指针等,它允许μC/OS-II跟踪哪些内存块是可用的,以及如何分配和回收它们。只有当内存控制块与分区结合后,系统才能进行有效的...
标题:“对uCOS-II内二维指针的研究” 描述:“对uCOS-II内二维指针的研究,加深对二维指针的理解” 在深入探讨uCOS-II操作系统中的二维指针应用之前,让我们首先简要回顾一下uCOS-II系统以及指针的基本概念。uCOS-...
介绍一种基于uC/OS-Ⅱ的三维运动平台控制系统的实现方案,该系统采用ARM7处理器作为主体,由嵌入式控制系统控制显示、检测、运动等任务。重点对系统的软硬件结构进行详细阐述,给出系统的设计流程,并对系统功能进行简要...
- UC/OS-II在每一个节拍服务里要遍历系统中的全部任务的任务控制块,把其中记录任务延时时间的成员`OSTCBDly`减1,并使延时时间到的任务进入就绪状态。 #### 八、时间管理 - **延时函数**: - UC/OS-II提供了延时...
本篇文章将详细讲解指针的使用,特别是`void`类型的指针以及二维指针的概念,同时也涉及`const`关键字在指针中的应用。 首先,我们来理解指针的基本概念。指针是一个变量,它存储的是另一个变量的内存地址。当我们...
二维数组arr与二级指针**arr 个人误区
二级指针常用于管理动态内存分配的多维数组,尤其是在处理二维数组时,能提供灵活且高效的访问方式。本示例通过一个简单的6行代码展示了如何使用二级指针对char类型的二维数组进行值操作。 二维数组在C++中本质上是...
### CJJ/T157-2010城市三维建模技术规范 #### 知识点解析 **一、背景介绍** 《城市三维建模技术规范》(CJJ/T157-2010)作为中国首个针对地理信息三维建模领域的技术规范,其发布标志着我国在该领域标准化工作上...
动态分配二维指针内存 在计算机编程中,动态分配二维指针内存是指在程序执行过程中动态地分配和释放内存的操作,以下是对动态分配二维指针内存的详细介绍: 1. 已知第二维的动态分配 在 C 语言中,可以使用 ...
### 基于数组指针实现二维数组中最小值所在行的查找与显示程序 #### 知识点一:理解数组指针与指针数组的区别 在C语言中,数组指针与指针数组有着本质的区别,它们在内存中的表示方式、使用场景以及功能上都存在...
`): 是一个指向含有 `n` 个整型元素的一维数组的指针,主要用于处理二维数组。 - **指针数组** (`int *p[n];`): 是一个包含 `n` 个整型指针的数组,每个元素都可以指向不同地址。 - **指向指针的指针**: 类似于 `...
这个练习要求我们创建一个名为"Line"的类,该类用于表示二维坐标系中的线段。线段由其两个端点定义,每个端点都有一个x和y坐标。下面是实现这个类的关键知识点: 1. **类的定义**: 类`Line`包含了四个私有数据...
对于二维数组,我们有两层指针:一层是指向数组的指针,另一层是数组中的元素指针。 二维数组的基本结构是这样的: ```cpp int arr[行数][列数]; ``` 例如,一个3x4的二维数组可以这样定义: ```cpp int arr[3]...
指向二维数组的指针 在编程中,指向二维数组的指针是非常重要的概念。二维数组是一种特殊的数组,它由多个一维数组组成。对于一个二维数组,例如 int a[3][4]={{0,1,2,3}, {4,5,6,7}, {8,9,10,11}};,可以看作是由...
因此,对于二维数组,我们可以获得其首元素的一维数组指针,这是一维数组指针的指针,也称为二级指针。 二维数组的声明通常如下所示: ```cpp int arr[3][4]; ``` 这个声明创建了一个3行4列的二维数组。数组`arr`...
二维数组与二重指针的探讨在程序设计语言中占有举足轻重的地位,它们是处理多维数据和复杂数据结构的基础。在本篇整理中,我们将深入探讨二维数组的本质,并结合二重指针来说明其在实际编程中的应用和注意事项。 ...
### 二维数组的动态分配与释放 在C和C++编程语言中,处理二维数组时经常需要进行动态分配和释放内存。这是因为静态分配的数组大小在编译时就已经确定,而实际应用中往往需要根据运行时的具体情况进行灵活调整。本文...
- **void指针**:类型不确定的指针。 - **函数指针**:指向函数的指针。 - **指针和动态内存分配**:使用malloc/realloc/free进行内存管理。 - **误用无效指针**:使用已释放或未初始化的指针可能引发错误。 - *...