edit:标题可能应该是“预处理器,CPP编译器到C编译器的转换问题。众所周知,预处理器是相同的。我认为问题出在那预处理的代码被编译后,与C编译器相比,CPP在布局方面更快乐。
关于如何使它与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:错误:案例标签未减少为整数常量 DYNAMIC_SWITCH_ELM(ident)
因此,CPP预处理器似乎愿意将const unsigned int值解释为其命令,而C预处理器或至少MPLAB的C预处理器则不这样做。
我唯一的选择是删掉DYNAMIC_SWITCH_BEGIN调用的某些内容,而是放置一个
#define ident __COUNT__
开关开头的。这也可行,但是我试图获得更强制的结构布局。
答案 0 :(得分:0)
请@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;
}