为什么#error指令不会给出预期结果?

时间:2018-01-02 18:15:44

标签: c embedded microcontroller

我正在写一篇" gpio"我的AVR ATmega32微控制器的设备驱动程序。驱动程序具有初始化功能,如下所示。我使用枚举将配置传递给函数。调用此函数的一个示例是

gpio_init_port(MY_PORT_A, INPUT, HIGH);

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

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;  
    }
}
}
}

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

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

提前致谢。

2 个答案:

答案 0 :(得分:6)

这些陈述

#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

"工作" (因为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);

答案 1 :(得分:3)

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

并且所有内容都不是来自#define is given a default macro value of 0

所以你的测试结果是

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

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