【问题标题】:CPP preprocessor to C preprocessor conversion questionCPP预处理器到C预处理器的转换问题
【发布时间】:2019-07-12 04:12:03
【问题描述】:

编辑:标题可能应该是“预处理器,CPP 编译器到 C 编译器的转换问题。据我所知,预处理器是相同的。在我看来,问题在于在编译预处理代码时,CPP 的布局比 C 编译器更满意。

关于如何使它与 C 预处理器兼容的任何建议?我试图用一种巧妙的方式为状态机创建一个灵活的 switch 语句,该语句有时会被调用,并在满足特定条件时前进。一旦它到达 switch 语句的末尾,它就会通过返回 true 来表示状态机已完成。我希望能够交换/插入步骤而不必重新分配案例值,所以这就是我在 CPP 中提出的,效果非常好。

#include <iostream>
#include <thread>

#define DYNCOUNT(start) (__COUNTER__-start)

#define DYNAMIC_SWITCH_BEGIN(identifier,switchElement) \
    const unsigned int identifier = __COUNTER__; \
    switch(switchElement){ \
        case 0:

#define DYNAMIC_SWITCH_ELM(identifier) \
    break; \
    case DYNCOUNT(identifier):

#define DYNAMIC_SWITCH_END \
    break; \
    };


bool stateMachine(unsigned int & state) {

    DYNAMIC_SWITCH_BEGIN(ident, state)
        std::cout << "A" << std::endl;
    //if(some_condition){
    state++;
    //}
    DYNAMIC_SWITCH_ELM(ident)
        std::cout << "B" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM(ident)
        std::cout << "C" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM(ident)
        std::cout << "D" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM(ident)
        std::cout << "E" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM(ident)
        std::cout << "F" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM(ident)
        std::cout << "G" << std::endl;
    //if(some_condition){
    state++;
    //}
    break;
        default:
            return true;
            DYNAMIC_SWITCH_END

                return false;
                //Visual Studios gets confused with the layout and structures it with this tabulation. 
}

int main() {

    unsigned int machineState=0;
    while(!stateMachine(machineState)){/*other operations*/}

    std::this_thread::sleep_for(std::chrono::seconds(5));
    return 0;
}

但是,当我尝试通过 MPLAB 在 C 环境中运行它时,我得到:

stateMachines.c:28:9: 错误:case 标签不会减少为整数常量 DYNAMIC_SWITCH_ELM(ident)

因此,CPP 预处理器似乎愿意将 const unsigned int 值解释为它的命令,而 C 预处理器,或者至少 MPLAB 的 C 预处理器却不愿意。

我唯一的选择是删除 DYNAMIC_SWITCH_BEGIN 调用的一些内容,而是放置一个

#define ident __COUNT__ 

在开关的开头。这也有效,但我试图获得更强制的结构布局。

【问题讨论】:

  • 两种语言使用相同的预处理器?
  • 我不确定,我个人对此不太了解,但在我的特殊情况下,我会说,可能不会,因为我正试图从 Visual Studios 迁移Microsoft 编译器,改用 MPLAB 的自定义编译器。
  • 1. C++ 和 C 使用相同的预处理器(规则)。 2. through MPLAB I get: XC 编译器有一长串已知的、无法修复的错误。将 PIC18 扔到垃圾桶并移至 stm32。 3.看起来你真的在重新设计protothreadspt
  • 这不是预处理器问题。 case (__COUNTER__-ident) 没有被 C 解析器评估为常量,而 C++ 解析器却将其评估为常量。
  • 您可以将const unsigned int identifier = …DYNAMIC_SWITCH_BEGIN中删除,并将开关更改为switch (switchElement __COUNTER__-1),并将其case 0:更改为case __COUNTER__:。那么DYNAMIC_SWITCH_ELM 中的情况将是case __COUNTER__:。换句话说,将 C 不喜欢的算术从 case 标签移到 switch 表达式中。

标签: c++ c preprocessor


【解决方案1】:

感谢@EricPostpischil 引导我找到这个解决方案。即使大小写值正在调整,开关也会表现得好像从 0 开始一样。由于它在幕后,因此 case 值不以 0 开头并不重要。

#include <iostream>
#include <thread>

#define DYNCOUNT(start) (__COUNTER__-start)

#define DYNAMIC_SWITCH_BEGIN(switchElement) \
    switch((switchElement + (__COUNTER__+1))){ \
        case __COUNTER__:

#define DYNAMIC_SWITCH_ELM \
    break; \
    case __COUNTER__:

#define DYNAMIC_SWITCH_END \
    break; \
    };


bool stateMachine(unsigned int & state) {

    DYNAMIC_SWITCH_BEGIN(state)
        std::cout << "A" << std::endl;
    //if(some_condition){
    state++;
    //}
    DYNAMIC_SWITCH_ELM
        std::cout << "B" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "C" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "D" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "E" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "F" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "G" << std::endl;
    //if(some_condition){
    state++;
    //}
    break;
        default:
            return true;
            DYNAMIC_SWITCH_END

                return false;
}

bool stateMachine_2(unsigned int & state) {

    DYNAMIC_SWITCH_BEGIN(state)
        std::cout << "H" << std::endl;
    //if(some_condition){
    state++;
    //}
    DYNAMIC_SWITCH_ELM
        std::cout << "I" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "J" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "K" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "L" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "M" << std::endl;
    //if(some_condition){
    state++;
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "N" << std::endl;
    //if(some_condition){
    state++;
    //}
    break;
        default:
            return true;
            DYNAMIC_SWITCH_END

                return false;
}

int main() {

    unsigned int machineState=0;
    while(!stateMachine(machineState)){}
    machineState = 0;
    while (!stateMachine_2(machineState)) {}

    std::this_thread::sleep_for(std::chrono::seconds(5));
    return 0;
}

编辑:

对于任何感兴趣的人,我在我的原始代码中添加了一些额外的有用工具,因此它不仅可以用于逐步推进的状态机,还可以包含环回或向前跳转,以防状态机更高级。仍然允许在任何需要的地方复制和粘贴或插入项目,与目标保持一致。

#define DYNAMIC_SWITCH_BEGIN(elementType,switchElement) \
    do{ \
    const elementType DYNAMIC_SWITCH_OFFSET=__COUNTER__+1; \
    elementType * __DYNAMIC_SWITCH_MODIFY_TARGET = & switchElement; \
    int __DYNAMIC_JUMP_FLAG=0; \
    switch((switchElement + DYNAMIC_SWITCH_OFFSET)){ \
        case __COUNTER__:

#define DYNAMIC_SWITCH_ELM \
    break; \
    case __COUNTER__:

#define DYNAMIC_ADV (*__DYNAMIC_SWITCH_MODIFY_TARGET)++;

#define DYNAMIC_SWITCH_DFLT \
    break; \
    default:

#define DYNAMIC_SWITCH_JUMP(jumpTag) \
    __DYNAMIC_JUMP_FLAG=1; \
    goto jumpTag;

#define DYNAMIC_SWITCH_TAGGED_ELM(jumpTag) \
    break; \
    case __COUNTER__: \
    case (__COUNTER__ +1): \
    jumpTag: \
    (*__DYNAMIC_SWITCH_MODIFY_TARGET) = __COUNTER__ - DYNAMIC_SWITCH_OFFSET; \
    if(__DYNAMIC_JUMP_FLAG)break; //Force to exit and complete on next loop for consistency in stepping behavior.

#define DYNAMIC_SWITCH_END \
    break; \
    }; \
    }while(0);

bool stateMachine(unsigned int & state) {

    DYNAMIC_SWITCH_BEGIN(unsigned int, state)
        std::cout << "A" << std::endl;
    //if(some_condition){
    DYNAMIC_ADV
    //}
    DYNAMIC_SWITCH_ELM
        std::cout << "B" << std::endl;
    //if(some_condition){
    DYNAMIC_ADV
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "C" << std::endl;
    //if(some_condition){
    DYNAMIC_ADV
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "D" << std::endl;
    //if(some_condition){
    DYNAMIC_ADV
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "E" << std::endl;
    //if(some_condition){
    DYNAMIC_ADV
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "F" << std::endl;
    DYNAMIC_SWITCH_JUMP(tag1)
    //if(some_condition){
    DYNAMIC_ADV
    //}

    DYNAMIC_SWITCH_ELM
        std::cout << "G" << std::endl;
    //if(some_condition){
    DYNAMIC_ADV
    //}
    DYNAMIC_SWITCH_TAGGED_ELM(tag1)
        std::cout << "H" << std::endl;
    DYNAMIC_ADV

    DYNAMIC_SWITCH_ELM
        std::cout << "I" << std::endl << std::endl;;
    //if(some_condition){
    DYNAMIC_ADV

    DYNAMIC_SWITCH_DFLT
        return true;
    DYNAMIC_SWITCH_END
        return false;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 2012-07-17
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多