C语言基础:typedef的使用

本文研究C语言中typedef关键字的作用。

1 typedef关键字的作用

本科学过C语言的朋友都知道数据类型的概念。C语言中有整型,如char、int、short等等;也有浮点类型,如float、double。

typedef关键字就是给这些数据类型起一个别的名字,然后用这个自己起的名字来定义变量。比如如下语句就把char类型起了个新的名字叫int8。然后用int8定义了一个变量a1。

typedef char int8;
int8 a1;

那么为什么不能直接用基础类型来定义变量,本文就研究其中的原因。

2 typedef关键字的场景

2.1 重新定义基本类型

Simulink生成的代码中,在rtwtypes.h头文件中专门有一组typedef,它们把一些基本类型,如char、float等,定义成别的名字。
在这里插入图片描述
然后定义变量的时候不去用基础类型定义,而是用int8_T,real32_T这些自己起名的类型去定义变量。
在这里插入图片描述
以前博主对此很费解,为啥要没事找事转一道。后来接触到MISRA-C规范后,才明白里面的意义。MISRA-C 2004规范的6.3条中说到,应该使用指示了大小和符号的typedef以代替基本数据类型
在这里插入图片描述
所以,把unsigned char用typedef转换成uint8_T的话,后面定义变量的时候就可以很清楚的知道这个变量是uint8的,范围是0~255。

另外,32位系统和64位系统中,基础类型对应的字节长度可能不同。如果整个工程中的代码全都是基础类型,再移植代码到新系统的时候可能要全部改一遍。而如果用了typedef,只需要改一下typedef这一句就行了。

2.2 为变量定义专属类型

首先思考一个场景。一个C语言工程中有很多函数,他们都需要传参数ObjNum,输入雷达检测到的目标个数。由于在函数定义的时候需要明确传递参数的数据类型,所以这些函数就定义成这样:

void function_1(uint8 ObjNum);
void function_2(uint8 ObjNum);
void function_3(uint8 ObjNum);

uint8最大可以表示255,如果想把ObjNum改成uint16类型的,就需要改3次(在大的工程中不止3个),所以一个好的办法就是用typedef,给这个变量定义一个专属的类型名称,如下:

typedef uint8 ObjNumType;
void function_1(ObjNumType ObjNum);
void function_2(ObjNumType ObjNum);
void function_3(ObjNumType ObjNum);

这样,只需要在typedef把uint8改成uint16就可以。

2.3 定义结构体、枚举量、数组

结构体由程序员自己定义,通常是把一些有着共同特征的变量打包在一起,以便增强可读性。例如,汽车动力学相关的变量就包括车速、横摆角速度、加速踏板等,可以把他们打包到一起定义一个结构体类型:

typedef struct VehicleDynamics_Tag
{
    float32 VehicleSpeed;
    float32 Yawrate;
    bool AccelerationPedal;
} VehicleDynamics_Type;

然后再用结构体类型定义一个结构体变量:

VehicleDynamics_Type vehicle_dynamics;

另外,枚举量的定义也类似,譬如定义LKA功能状态:

typedef enum LKAStatus_Tag
{
    LKA_OFF= 0,
    LKA_STANDBY,
    LKA_ACTIVE,
    LKA_OVERRIDE
} LKAStatus_Type;

对于数组定义,可以看一个例子。

#include <iostream>

typedef unsigned char ObjID[10];

int main()
{
    ObjID id;

    for (int i = 0; i < 10; i++)
    {
        id[i] = i;
    }
    printf("id[4] = %d\r\n", id[4]);
    printf("id = %p\r\n", id);
}

用typedef定义一个无符号整型的数组类型ObjID[10],这表明类型是ObjID,数组size是10。在主函数中再通过ObjID定义id,注意这里的id变量指的是数组的首地址。再通过下标就可以访问数组元素,例如id[4]。

打印数组元素和数组地址如下图:
在这里插入图片描述

3 总结

目前博主工作中遇到的typedef主要就是以上3种非常常见的情况。

>>返回个人博客总目录

  • 26
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是使用栈和队列实现停车场管理的C语言代码: ```c #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 // 定义停车场最大容量 typedef struct { char type; // 到达/离去 int id; // 汽车牌照号码 int time; // 到达/离去的时刻 } Car; typedef struct { int top; // 栈顶指针 Car data[MAX_SIZE]; // 栈元素 } ParkStack; typedef struct { int front; // 队头指针 int rear; // 队尾指针 Car data[MAX_SIZE]; // 队列元素 } WaitQueue; int park[MAX_SIZE]; // 停车场 int park_top = -1; // 停车场栈顶指针 ParkStack park_stack; // 停车场栈 WaitQueue wait_queue; // 等待队列 // 初始化停车场栈 void init_park_stack() { park_stack.top = -1; } // 检查停车场是否为空 int is_park_empty() { return park_stack.top == -1; } // 检查停车场是否已满 int is_park_full() { return park_stack.top == MAX_SIZE - 1; } // 将车辆停放在停车场中 int park_car(Car car) { if (is_park_full()) { // 停车场已满,将车辆加入等待队列 if (wait_queue.rear == MAX_SIZE - 1) { // 等待队列已满,无法加入新车辆 return 0; } wait_queue.rear++; wait_queue.data[wait_queue.rear] = car; return 1; } else { // 停车场未满,将车辆停放在停车场内 park_top++; park[park_top] = car.id; park_stack.top++; park_stack.data[park_stack.top] = car; return 1; } } // 从停车场中取出车辆 int unpark_car(Car car) { int i, j, flag = 0; int time = 0; for (i = 0; i <= park_top; i++) { if (park[i] == car.id) { // 找到对应的车辆 flag = 1; time = car.time - park_stack.data[i].time; // 将车辆从停车场中移除 for (j = i; j < park_top; j++) { park[j] = park[j+1]; } park_top--; park_stack.top--; break; } } if (!flag) { // 停车场中没有找到对应的车辆,可能已经离开停车场 return 0; } else { // 计算停留时间和停车费用 int fee = time <= 2 ? 5 : (time - 2) * 3 + 5; printf("车辆 %d 在停车场内停留 %d 分钟,需缴纳停车费用 %d 元\n", car.id, time, fee); if (!is_park_empty()) { // 停车场不为空,将等待队列中的车辆加入停车场 Car next_car = wait_queue.data[wait_queue.front+1]; park_car(next_car); wait_queue.front++; wait_queue.rear--; } return 1; } } // 主函数 int main() { // 初始化停车场栈和等待队列 init_park_stack(); wait_queue.front = 0; wait_queue.rear = -1; // 输入车辆信息 printf("请输入车辆信息(格式:到达/离去,汽车牌照号码,到达/离去的时刻),输入 E 0 0 结束输入:\n"); char type; int id, time; while (1) { scanf("%c %d %d", &type, &id, &time); getchar(); // 读取输入缓冲区的回车符 if (type == 'E' && id == 0 && time == 0) { break; } Car car = {type, id, time}; if (type == 'A') { // 汽车到达,尝试将车辆停放在停车场中 if (!park_car(car)) { printf("停车场已满,车辆 %d 无法停放\n", car.id); } else { printf("车辆 %d 停放在停车场中\n", car.id); } } else if (type == 'D') { // 汽车离开,尝试将车辆从停车场中移除 if (!unpark_car(car)) { printf("车辆 %d 不在停车场中\n", car.id); } } } return 0; } ``` 注意,上述代码中使用了两个全局变量 `park` 和 `park_top` 来表示停车场,这不是一个很好的实现方式,更好的实现方式是将停车场用一个栈来表示。在上述代码的基础上,你可以尝试使用栈来实现停车场,以提高代码的可读性和可维护性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值