由于工作需要,要把uboot中的pci扫描代码移植到自己的项目里来,本来都做好了,但是需要稍微修改下uboot里的几个专门为我们的项目使用的文件,
也就是uboot导出的函数,供项目使用,但是被告知,目前uboot已经是发布的版本,不能再改变了。
怎么办呢?其实pci系统在uboot起来的时候已经初始化好了,在代码中需要的是其中一些变量的地址,有了这些地址,转换成合适的指针,那么就可以进行操作了,
这里主要研究类型问题。
举例,由易到难:
int a = 5;
已知a的地址为 0xffff0000;
也就是 &a == 0xffff0000 成立
#define ADDR_OF_A 0xffff0000
以供使用
那么我们想使用a这个变量,也就是能读写a,但是已知的只有ADDR_OF_A
大家都会想到这么做
int *p = (int *)ADDR_OF_A
然后,对p的引用就相当于操作a,比如*p = 6; 则a的值改变为6.
有没有想过为什么能这么做呢,弄明白这里对理解指针大有裨益。
a的类型是一个整型,那么需要一个整型指针来表示其地址。
以此类推,a是什么类型,就需要一个什么类型的指针指向其地址!
下面再举个例子
int b = 1;
int *ptr = &b;
#define ADDR_OF_PTR 0xffff0000
假如现在知道ptr的地址(&ptr),该怎么进行表示它呢?
ptr是一个指针,很明显,我们需要的是一个指向指针的指针
int **temp;
temp = (int **)ADDR_OF_PTR;
这样,在进行*temp的时候就相当于对ptr 操作。
比如
int c = 3;
*temp = &c;
这样,就改变了ptr,相当于ptr = &c;
好了,上述都是基本类型。下面分析一个本项目中遇到的类型
struct fsl_pci_info *pci_info_list[5] = { NULL, NULL, NULL, NULL, NULL} ;
这个是uboot代码中定义的,现在知道了它的地址(&pci_info_list),
#define PCI_INFO_LIST_ARRAY 0x7fff0b6c
要对其进行引用,需要仔细分析下类型。
首先,pci_info_list是一个数组,该数组包含5个元素,类型为结构体指针struct fsl_pci_info *
好,根据上面的分析,我们需要一个指针,指针的类型是指向一个包含5个元素的数组,很显然是一个指向数组的指针。
应当做如下定义
struct fsl_pci_info *(*ptr)[5];
ptr = (struct fsl_pci_info * (*)[5])PCI_INFO_LIST_ARRAY;
怎么样,感到复杂吗?
其实只要分析一下,也并不是那么复杂。分析类型
struct fsl_pci_info * (*)[5];
根据运算符的优先级,()内最高,所以是一个指针,后面跟[5],所以说明了指针指向了一个数组,前面的类型是数组元素的类型!
下面是使用部分,真正需要的是要把这个数组中的元素取出来
struct fsl_pci_info *pci_info;
pci_info = (*ptr)[i];
ptr 类型是指向数组的指针,那么*ptr的类型就是数组类型啦!
本文主要讲述C语言中指针的类型。C语言中数据类型的唯一作用就是告诉编译器:变量在内存中是怎么存储的,在使用的时候要按照类型大小来。
比如char ch;
字符型,那么在取数据的时候,不如int inter = ch; 只取&ch 地址开始的一个字节。
如果是int a; int b = a;
则需要取&a开始的 sizeof(a) 也就是4个字节。
还有,一个指针的类型决定了指针在做增量的时候的步进长度。
比如
char a;
char *ptr = &a;
ptr++;
ptr++使ptr指向了下一个字节。
如果是
int a;
int *ptr =&a;
ptr++;
则ptr指向了下一个Int型数据,也就是步进长度为sizeof(a).
如果是个结构体指针,同理,变为sizeof(struct XXX).
其他类型以此类推。