当前位置: 首页 > 代码生活 > 正文

C语言数组赋值一例

在移植内核时,发现一个驱动使用数组十分巧妙。
一般地,操作CPU某一外设寄存,不是直接使用完整的地址,而是通过相对地址来访问。比如,访问定时器,首先参考手册定义好定时器基地址,然后再定义寄存器(如控制寄存器、读数据寄存器等)对于定时器基地址的偏移地址。在使用时,一般都是使用偏移地址的,这样十分方便、快捷。如果有七、八个定时器,只需要定义好一个基地址数组、一个偏移地址数组,通过不同的序号就能访问不同的地址。
本文的例子是从驱动中抽象出来的。一个芯片平台系列中,对于特定外设,大部分的地址是相同的,但还是有个别不同,为了适应不同的芯片,代码也要做些处理。比如,这个系列中有十个寄存器,但另一个系统只有五个,其中大部分是共用的,为了共用代码,把所有的寄存器用枚举类型对一个数组进行访问,从而得到实际的偏移地址。
这里的数组赋值形式是我之前没见过,下面的例子中foo_regs数组,如果转化成实际值,变成:

static const u32 foo_regs[] = { [0] = 0x00, [3] = 0x48, [2] = 0x3c,};

这种赋值的好处在于,可以根据不同的情况使用不同的下标、不同的值。比如,同样是控制寄存器FOO_CTRL_REG,有的平台是0x3c,有的是0x3f,这样就可以通过不同的数组区别开来,而对外的访问接口,可以做到统一。

完整示例代码如下:

#include <stdio.h> #include <stdlib.h> #include <string.h> #define u32 unsigned int enum { FOO_ID_REG = 0, FOO_SYS_STAT_REG, FOO_CTRL_REG, FOO_COUNTER_REG, }; static const u32 foo_regs[] = { [FOO_ID_REG] = 0x00, [FOO_COUNTER_REG] = 0x48, [FOO_CTRL_REG] = 0x3c, }; static const u32 bar_regs[] = { [FOO_ID_REG] = 0x00, [FOO_CTRL_REG] = 0x3f, [FOO_COUNTER_REG] = 0x4f, }; #define FOO_START (1 << 0) #define FOO_STOP (1 << 1) static u32 foo_read_reg(unsigned int timer, u32 reg) { u32 tmp = 0; tmp = (timer + (foo_regs[reg] & 0xff)); printf("%x: %x\n", reg, tmp); } static u32 foo_write_reg(unsigned int timer, u32 reg, u32 value) { u32 tmp = 0; tmp = (timer + (bar_regs[reg] & 0xff)); printf("%x: %x\n", reg, tmp); } int main(void) { foo_read_reg(0x80084000, FOO_COUNTER_REG); foo_write_reg(0x80084000, FOO_COUNTER_REG, FOO_START); return 0; }

运行结果:

3: 80084048 3: 8008404f

从这里学习到一个数组的赋值的方法,即实际赋值可以按不同的顺序(只要是合法的下标),而不是仅限于从0~N这样的顺序去赋值。

李迟记于2014年2月28日

本文固定链接: http://www.latelee.org/code-life/c-array-assign.html

如无特别说明,迟思堂工作室文章均为原创,转载请注明: C语言数组赋值一例 | 迟思堂工作室

目前暂无评论

发表评论

*

快捷键:Ctrl+Enter