定义一个地址固定的变量

在阅读uboot源码,linux内核,一些单片机平台的系统头文件中,经常会遇到定义一个固定地址的变量。理解它们的用法对于阅读源码很有帮助。

首先看一个熟悉的定义:

#define GPFCON	(*(volatile unsigned int*)5000)

#define GPFCON	(*(volatile unsigned char*)5000)

这两句话的意思是:1,定义unsigned int 型变量GPFCON,并绑定变量所在的内存地址为5000;2,定义一个unsigned char型的变量GPFCON,并绑定变量所在的内存地址为5000。

下面是在icc编译环境下写的C语言代码:

/*just for test*/
#define GPFCON	(*(volatile unsigned int*)5000)

void main()
{
	GPFCON = 0x01 ;
}

查看列表文件的结果为:

 0000           ; #define GPFCON        (*(volatile unsigned int*)5000)
 0000           ; 
 0000           ; void main()
 0000           ; {
 0000                   .dbline 6
 0000           ;       GPFCON = 0x01 ;
 0000 81E0              ldi R24,1
 0002 90E0              ldi R25,0
 0004 90938913          sts 5000+1,R25
 0008 80938813          sts 5000,R24
 000C                   .dbline -2
 000C           L1:
 000C                   .dbline 0 ; func end
 000C 0895              ret
 000E                   .dbend
 000E           ; }
很明显看到汇编程序将0x01放入了地址为5000和5001的两个连续的地址空间里。实验证明这种定义固定地址变量的方法是有效的。

#define GPFCON	(*(volatile unsigned char*)5000)
验证结果为:汇编程序将0x01放入了地址为5000的一个字节地址空间里。

下面我们看一段uboot源码中的一段代码:

#define S3C2410_NAND_BASE		0x4E000000//寄存器基地址

static inline struct s3c2410_nand *s3c2410_get_base_nand(void)
{
	return (struct s3c2410_nand *)S3C2410_NAND_BASE;
}
/* NAND FLASH (see S3C2410 manual chapter 6) */
struct s3c2410_nand {
	u32	NFCONF;
	u32	NFCMD;
	u32	NFADDR;
	u32	NFDATA;
	u32	NFSTAT;
	u32	NFECC;
};//寄存器相关

函数static inline struct s3c2410_nand *s3c2410_get_base_nand(void);的返回值类型为 struct s3c2410_nand *,这种类型可以描述为某种结构体的指针。

return (struct s3c2410_nand *)S3C2410_NAND_BASE;
告诉我们函数return的类型是一个指针地址为0x4E000000的指向 struct s3c2410_nand结构体的指针变量。从语法角度,将S3C2410_NAND_BASE强制转换为一个指针类型(一般为四个字节大小),指向一个连续六个U32类型的地址空间。

所以这个函数的作用可以理解为从某基地址申请一段连续内存地址空间。




### C语言结构体指针变量赋值方法 在C语言中,可以通过多种方式为结构体指针变量赋值。以下是几种常见的方法: #### 1. 使用地址运算符 (`&`) 获取结构体变量地址 如果已经有一个结构体变量,则可以直接通过取址操作将其地址赋予结构体指针变量。 ```c #include <stdio.h> struct Student { int id; char name[20]; }; int main() { struct Student s = {1, "Alice"}; // 定义一个结构体变量s struct Student *p = &s; // 将s的地址赋值给指针p printf("ID: %d, Name: %s\n", p->id, p->name); return 0; } ``` 这种方式是最常见也是最基础的方式之一[^1]。 #### 2. 动态分配内存并通过 `malloc` 函数创建结构体实例 当不确定具体需要多少个结构体实例或者希望灵活管理内存时,可以使用动态内存分配函数 `malloc` 来创建一个新的结构体实例,并将返回的地址赋值给结构体指针变量。 ```c #include <stdio.h> #include <stdlib.h> // 包含 malloc 和 free 的头文件 struct Employee { int emp_id; double salary; }; int main() { struct Employee *e = (struct Employee *)malloc(sizeof(struct Employee)); // 动态分配内存 e->emp_id = 101; e->salary = 5000.0; printf("Employee ID: %d, Salary: %.2f\n", e->emp_id, e->salary); free(e); // 记得释放动态分配的内存 return 0; } ``` 这种方法适用于运行期间未知大小的数据集或临时对象的场景[^2]。 #### 3. 利用数组中的元素作为目标来完成指针赋值 对于已知数量固定的多个同类型结构体组成的集合(通常表现为数组形式),也可以很方便地让某个特定位置上的项目成为所关注的对象。 ```c #include <stdio.h> struct Book { char title[50]; float price; } books[] = {{"Book A", 29.99}, {"Book B", 39.99}}; // 初始化书籍列表 void display_book_info(const struct Book* b){ printf("Title:%s Price:$%.2f\n",b->title,b->price ); } int main(){ const struct Book *current_book=&books[0]; // 设置当前书本索引到第一个条目处 while(current_book<&books[sizeof(books)/sizeof(*books)]){ display_book_info(current_book++);// 显示每本书的信息直到结束为止 } return 0 ; } ``` 这里展示了如何遍历整个结构体数组并将每个元素依次传递给函数进行处理的过程[^3]。 以上就是关于C语言中针对不同类型需求下实现对结构体指针变量的有效赋值手段介绍。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值