typedef的一些用法及注意事项

时间:2021-10-26 15:46:38

1、引言

       在公司新仪器的研制项目中用了ALTERAEP2C5系列FPGA控制DDS产生波形并控制AD进行数据采集,并采用串口和其他电路通信。在编写测试仿真模拟串口时就想在单片机里那么简单的功能在FPGA里怎么这么麻烦。后来和同事交流得知可以利用NIOS IIFPGA里边嵌入软核使FPGA变成单片机。当时感觉很神奇,于是就想研究研究NIOS II 到底是什么东西。在网上浏览了很多NIOS II的帖子后,感觉很有趣决定深入学习一下。于是购买了人气很高的黑金开发板。接下来一有时间就照着《NIOS II 那些事》里的例程来学习。在学习的过程中逐渐的感觉到自己的C语言知识还很渣。好多概念还有没掌握。因此决定把这些概念重新学习一下。


2、typedef关键字简介

       首先是关键字typedeftypedefC/C++的一个关键字,主要用途是为数据类型创建新的名字。它不能和autoexternstaticvolatile等其他关键字出现在一个表达式里。一般使用typedef有两个目的,一是给变量定义一个简单易懂且意义明确的新名字,二是简化复杂的类型声明。


3、typedef的一个应用实例

       在黑金开发板上学习编写NIOS外设驱动程序时,总是遇到typedef + struct。比如下图所示的I/O驱动程序。这段程序定义了一个名为PIO_STR的结构体,然后定义了LED的宏,(PIO_STR *PIO_LED_BASE实质是一个结构体变量,这个结构体变量是由指向PIO_LED_BASEPIO_STR结构体的指针来实现的,指针指向的地址就是PIO_LED_BASE。而PIO_LED_BASEFPGA中用于驱动LEDIO口的寄存器的基地址。结构体成员和PIO寄存器的内容一一对应。(PIO_STR *PIO_LED_BASE这个语句就把结构体的起始地址和PIO寄存器的基地址对应起来。如此一来就可以通过操作结构体的成员来对PIO寄存器进行读写。比如拉低驱动LED引脚的电平可以采用下面的语句实现:


       typedef的一些用法及注意事项

       typedef的一些用法及注意事项

图1  PIO_STR 结构体定义


typedef的一些用法及注意事项

图2 PIO寄存器


         通过宏定义分别把结构体的基地址设置为不同的寄存器基地址,就可以通过操作结构体来实现对NIOS II寄存器的操作。

       扯的有点远了,但是实在是惊叹上述编程方式的巧妙。

       在上边结构体的定义中,采用typedef定义了PIO_STR结构体。PIO_STR就相当于结构体的名称。实际应用中可能需要用到很多I/O口,这些I/O的寄存器都是一样的,因此我们只需要把结构体基地址和相应的I/O口寄存器基地址对应起来就可以。比如下边的语句就定义了和RTC连接的三个I/O端口。


         typedef的一些用法及注意事项


         上边的例子中通过使用typede定义了新的PIO_STR类型,使代码变的简洁。


4、typedef的其他用法和注意要点

          typedef除了以上的用法外还有其他的用法及使用要点。

      (1)和#define的区别

       typedef看起来和#define很像,其实两者是不一样的。#define仅仅是简单的文本替换,在编译预处理时把宏定义用原始文本替换。而typedef超越了文本替换,是为数据类型重新定义名字,因此不能简单文本替换代替,需要在编译时由编译器来应对解释处理。

      (2)平台无关性

       typedef另一个重要作用就是定义与平台无关的数据类型。比如可以定义一个ANGLE浮点类型来获取最高的数据精度:

          typedef的一些用法及注意事项

        如果平台不支持long double,可以把定义修改如下:

           typedef的一些用法及注意事项

       如果连double类型都不支持,可以修改如下:

           typedef的一些用法及注意事项

       这样代码在平台间进行移植时,仅需要修改typedef定义就可以了,不需要修改其他代码。好多标准库或者驱动程序就是采用这种方法。而typedef不是简单的文本替代因此比#define用起来更可靠。