【问题标题】:Why doesn't #error directive give the expected result here?为什么#error 指令在这里没有给出预期的结果?
【发布时间】:2018-01-02 18:15:44
【问题描述】:

我正在为我的 AVR ATmega32 微控制器编写“gpio”设备驱动程序。驱动程序具有如下所示的初始化函数。我使用枚举将配置传递给函数。调用这个函数的一个例子是

gpio_init_port(MY_PORT_A, INPUT, HIGH);

这会将 PORTA 设置为默认值 HIGH 的输入。我使用 switch 语句检查传递的配置以将相应的端口设置为输入或输出。现在我想在switch语句的“默认”情况下使用#error预处理器指令,以防用户输入错误的输入,例如

gpio_init_port(5, INPUT, HIGH);

因此编译停止并打印错误消息。但我不知道为什么它没有按我的预期工作。我指的代码部分是这样的:

default:
#if (port_number != MY_PORT_A && port_number != MY_PORT_B && port_number != MY_PORT_B && port_number!=MY_PORT_D)
#error "Wrong Input. You have entered invalid port number."
#endif

表达式

(port_number != MY_PORT_A && port_number != MY_PORT_B && port_number != MY_PORT_B && port_number!=MY_PORT_D)

不评估并且不打印错误消息。但是当我把它改成

#if (1)
#error "Wrong Input. You have entered invalid port number."
#endif

它工作正常。 我遇到的另一个问题是,当我写类似的东西时

gpio_init_port(5, ***OUTPUT***, HIGH);

虽然我这次传递了“OUTPUT”,但也打印了错误消息,这不应该发生,因为默认情况仅针对“INPUT”情况定义。

gpio.h
______

typedef enum port_number{
   MY_PORT_A=0,
   MY_PORT_B,
   MY_PORT_C,
   MY_PORT_D
} port_number_t;
typedef enum port_direction{
   INPUT=0,    
   OUTPUT
} port_direction_t;
typedef enum output_state{
   LOW=0,
   HIGH
}output_state_t;
void gpio_init_port(port_number_t port_number, port_direction_t port_direction, output_state_t initial_value);

gpio.c
________
#include "gpio.h"
void gpio_init_port(port_number_t port_number, port_direction_t port_direction, output_state_t initial_value)  
{
switch (port_direction)
{
case INPUT:
{
    switch (port_number)
    {
    case MY_PORT_A:
    DDRA=0x00;
    PORTA=initial_value? 0xff:0x00;
    break;
    case MY_PORT_B:
    DDRB=0x00;
    PORTB=initial_value? 0xff:0x00;
    break;
    case MY_PORT_C:
    DDRC=0x00;
    PORTC=initial_value? 0xff:0x00;
    break;
    case MY_PORT_D:
    DDRD=0x00;
    PORTD=initial_value? 0xff:0x00;
    break;
    default:
    #if (port_number != MY_PORT_A && port_number != MY_PORT_B && port_number != MY_PORT_B && port_number!=MY_PORT_D)
    #error "Wrong Input. You have entered invalid port number."
    #endif
    break;
    }
}
case OUTPUT:
{
    switch (port_number)
    {
    case MY_PORT_A:
    DDRA=0xff;
    PORTA=initial_value? 0xff:0x00;
    break;
    case MY_PORT_B:
    DDRB=0xff;
    PORTB=initial_value? 0xff:0x00;
    break;
    case MY_PORT_C:
    DDRC=0xff;
    PORTC=initial_value? 0xff:0x00;
    break;
    case MY_PORT_D:
    DDRD=0xff;
    PORTD=initial_value? 0xff:0x00;
    break;  
    }
}
}
}

那么,这里到底出了什么问题?

我读到枚举不能用于条件编译,但我不知道这是否真的正确以及问题的原因。

提前致谢。

【问题讨论】:

  • 请避免同时提出多个问题。
  • @klutt,伙计,这些多个问题在哪里?!!
  • 也许我有点快。原因是你写了“Another issue that I have”,但我会撤回接近投票。

标签: c embedded microcontroller


【解决方案1】:

这些陈述

#if (port_number != MY_PORT_A && port_number != MY_PORT_B && port_number != MY_PORT_B && port_number!=MY_PORT_D)
#error "Wrong Input. You have entered invalid port number."
#endif

在预处理/编译时进行评估。因此,无论switch 语句的结果如何,都会对它们进行评估。在这种情况下,您将尝试测试 port_number,它是 #if 宏中的一个变量,这是不可能的。

一般来说,#error 指令很有用,例如当某些预处理器常量发生冲突时,在编译时,当然不是在运行时。你引用的例子

#if (1)
#error "Wrong Input. You have entered invalid port number."
#endif

“works”(其实它不是很有用)因为1 是一个编译时常量。

您想在运行时对其进行测试,并在运行时抛出一种“异常”:

default:
{
   fprintf(stderr,"at %s line %d: Wrong Input. You have entered invalid port number.\n",__FILE__,__LINE__);
   exit(1);
}

不需要if,因为switch声明已经排除了所有4个案例。

还请注意,您可以插入方便的 __FILE____LINE__ 编译时值,以便知道在源代码中的哪个位置引发了错误(除非您想直接使用 assert(0);

【讨论】:

    【解决方案2】:

    预处理器#if 只能测试之前已经#define'ed 的值。它对变量、参数或枚举值一无所知。

    以及并非来自#define is given a default macro value of 0 的所有内容。

    所以你的测试结果是

    #if (0 != 0 && 0 != 0 && 0 != 0 && 0 !=0)
    

    这当然不会触发#error 消息。

    【讨论】:

      猜你喜欢
      • 2015-10-07
      • 2013-11-21
      • 2013-12-20
      • 2018-06-04
      • 2019-11-14
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      • 2014-10-16
      相关资源
      最近更新 更多