Вопрос преобразования препроцессора CPP в C - PullRequest
0 голосов
/ 18 февраля 2019

edit: Заголовок, вероятно, должен быть "Препроцессор, вопрос преобразования компилятора CPP в C. Как мне стало известно, препроцессоры одинаковы. Мне кажется, что проблема в том, что результаткомпилируемый предварительно обработанный код, CPP более доволен компоновкой по сравнению с компилятором C.

Любой совет, как мне сделать это совместимым с препроцессором C? Я пытался сделать изящный способ созданиягибкий оператор переключения для конечного автомата, который вызывается при возникновении определенных событий и продвигается при выполнении определенных критериев. Как только он достигает конца оператора переключения, он сигнализирует, что конечный автомат завершил работу, возвращая значение 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;
}

Однако, когда я пытаюсь запустить его всреда C через MPLAB я получаю:

stateMachines.c: 28: 9: ошибка: метка случая не повторяетсяиз-за целочисленной константы DYNAMIC_SWITCH_ELM (идент.)

Таким образом, кажется, что препроцессор CPP желает интерпретировать значение const unsigned int в свои команды, в то время как препроцессор C или, по крайней мере, препроцессор C MPLAB, делаетнет.

Моя единственная альтернатива - обрезать часть содержимого вызова DYNAMIC_SWITCH_BEGIN и вместо этого поместить

#define ident __COUNT__ 

в начале коммутатора.Это тоже работает, но я пытался получить более строгую структуру структуры.

1 Ответ

0 голосов
/ 18 февраля 2019

Благодарим @EricPostpischil за то, что он привел меня к этому решению.Переключатель будет вести себя так, как если бы он начинался с 0, даже если значения настроек корректируются.Поскольку это негласно, на самом деле не имеет значения, что значение регистра не начинается с 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...