c中的typedef枚举说明

时间:2015-12-07 11:25:31

标签: c typedef

我正在查看微控制器上ADC的头文件,其中包含以下代码。

/**
 * ADC channels type.
*/

typedef enum {
    ADC_CH_0,
    ADC_CH_1,
    ADC_CH_2,
    ADC_CH_3,
    ADC_CH_4,
    ADC_CH_5,
    ADC_CH_6, 
} adc_channel_t;

在ADC的main.c中有以下代码行

adc_channel_t channels[] = {ADC_CH_4, ADC_CH_5};

我想知道你为什么需要为ADC声明新的数据类型?什么typedef枚举意味着什么?

由于

4 个答案:

答案 0 :(得分:6)

作为artm答案的补充,typedef添加在enum前面,以便于enum的使用。如果声明看起来像这样:

enum adc_channel_t {
    ADC_CH_0,
    ADC_CH_1,
    ADC_CH_2,
    ADC_CH_3,
    ADC_CH_4,
    ADC_CH_5,
    ADC_CH_6, 
};

然后行adc_channel_t channels[] = {ADC_CH_4, ADC_CH_5};必须写成:

enum adc_channel_t channels[] = {ADC_CH_4, ADC_CH_5};

typedef允许我们在每次使用该类型时忽略enum

使用有用的常量通常优于"魔术数字",虽然在这种情况下看起来有点奇怪但常量几乎不提供额外的信息。然而,它可以是有用的,因为枚举器用作额外的描述。例如,期望值为adc_channel_t的IDE的IDE将能够建议可能是有效值范围的频道:ADC_CH_0ADC_CH_6,而不是简单地告诉您使用数字。

答案 1 :(得分:4)

为什么要这样做有多个组成部分。

  1. typedef做什么
  2. 为什么要键入枚举枚举
  3. typedef允许您定义新类型。这样可以让您的意图更清晰。

     char id; // but my id is a number!
     typedef unsigned char uint8; // ok now we can use uint8 instead of char
     uint8 id; // better! Now we know we should only interpret id as a number.
    

    在C语言中,你需要在引用时指定enumstruct

    enum CarModels_e {
        Bravia,
        Uno
    };
    
    
    enum CarModels_e the_model;
    enum CarModels_e other_model
    // this gets boring fast...
    

    所以程序员(懒惰的人)会尽量避免打字。为此他们创建了一个新类型:

    typedef enum CarModels_e CarModels; // now we don't need to type enum every time!
    
    CarModels the_model;
    CarModels other_model
    // Less typing! Happier programmer!
    

    但是你仍然需要输入两次enum CarModels_e,所以他们在一个声明中也将它们结合起来:

    typedef enum /* Don't even need a name here anymore! Much less typing :) */ {
        Bravia,
        Uno
    } CarModels;
    

    为什么直接使用enum代替数字?因为这样你可以赋予数字意义。因此,下次他们(或其他任何人)阅读他们的代码时,他们仍然知道这些数字是什么。

    // Example
    if (measured_frequency == 12345) { // hmm where does this come from?
    
    if (measured_frequency == MaximumMotorFrequency) { // Ah! Now i'll know what this is about in ten years!
    

答案 2 :(得分:1)

  

我想知道你为什么需要为ADC声明新的数据类型?什么typedef枚举意味着什么?

typedef enum是一种对相关常量进行分组的方法。您可以从constADC_CH_0声明七个ADC_CH_6,但由于它们都是相关的,因此最好在此使用enum(每个enum常量为默认情况下增加1)。

稍后您可以使用类型adc_channel_t来声明变量,并保证范围在声明的枚举常量范围内。

答案 3 :(得分:0)

我首选的执行方法如下:

typedef enum powerState_tag {
    PS_OFF,
    PS_ON
} powerState_te;

这可以在一个表达式中执行多项操作。

  1. 声明枚举pwerState_tag {PS_OFF,PS_ON}。
  2. 创建powerState_te的类型定义。

出于某些代码解析器/编辑器的目的,我通常添加pwerState_tag来将枚举显示为未命名。我添加后缀以指示_tag是枚举的名称,而_te是类型化的枚举。为了对称起见,我在_tag和_te中都重复了该名称。这些不是标准化的命名约定,除非您的编码标准另有规定,否则可以将其命名为任何名称。 Barr Group拥有一个在线标准,在很多工作中我都曾提到过该标准,并且相当不错。他们不使用_te来识别它是什么类型的typedef。

以这种方式定义枚举的最大好处是,如果有人传入了未定义的值,则编译器会在编译时通知您。

例如,下面的示例在上面的示例中会导致编译时错误:

adc_channel_t channels[] = {99, -1};

但是以下操作不会失败,因为枚举中包含4和5:

adc_channel_t channels[] = {4, 5};

某些编辑器也使用typedef枚举来自动填充。

adc_channel_t channel;
// when you begin to assign the value, the editor will offer suggestions
channel = AD \\<auto completes up to _> and you have to merely type the number of click the value you like. 

我工作过的大多数未使用typedef枚举模式的代码都将传入一个通用int,而不指定它是枚举,而是像#define一样使用ADC_CH_4。

uint8_t getAdcVal(uint8_t channel); // A
uint8_t getAdcVal(adc_channel_t channel); //B

尽管当用户使用有效范围时A可以正常运行,但是编译器没有像在B时那样验证其在枚举时的范围内。

Barr Group's coding standard