这个 switch case 构造有更好的实现吗?
Is there any better implementation for this switch case construct?
我正在开发一个嵌入式系统,其中必须访问一个寄存器,然后递增以获得我正在寻找的结果,因为机器正在通知并配置为对我的访问和更改做出反应或不更改标志。所以 switch
的参数必须保持原样,否则它会改变嵌入式系统的行为。
但可能会出现我不想调用任何案例的情况。但是我仍然需要访问并增加 switch
.
的参数
(更深入我正在逐步将一系列模拟值转换为数字值转换。索引用于与当前转换保持同步并将其与相应的案例相关联以正确处理数字。有可能会出现索引与当前转换不同步的状态,因此转换序列必须 运行 通过,而不会调用任何情况(以防止设置错误的数据),直到序列完成并且可以重新同步执行)
我目前的做法是这样的:
switch (RunIndex++)/*RunIndex may only be accessed one time per execution
of this construct and has to be incremented in the same step. thats given.*/
{
if (RunIndexSyncedWithADCensured == false)
{
break;
}
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
case 1:
Case1RelatedData = SomeOperationsForCase1(RawData);
break;
case 2:
Case2RelatedData = SomeOperationsForCase2(RawData);
break;
default:
RunIndex = 0;
break;
}
这个构造完成了工作,但它看起来有点争议,考虑将其提交到产品代码中我感觉不太好。
那么有没有更好看的方法来实现相同的目标,而不需要额外的变量或赋值?
注:
这也可能是相关的,它位于由两部分组成的中断函数的第一部分。
第一部分处理必须发生的事情 if()
转换完成。第二部分,还有什么需要做的if()
这个转换也结束了序列。因此,在不进入第二部分的情况下,从函数中简单地 return 是没有选择的。目前还没有 if(...)break;
可能爆发的循环结构。 (这也是我将 if 放在 switch 范围内的原因,因为它至少按照标准是一种有效的突破方式。)
首先,switch()
里面的if()
永远不会被执行。
考虑以下代码片段:
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 2;
switch(i) {
if (i == 2) {
printf("I M HERE\n");
}
case 1:
printf("1\n");
break;
case 2:
printf("2\n");
break;
default:
printf("default\n");
break;
}
return 0;
}
对于您的代码:您希望打印字符串 I M HERE
。但事实并非如此。
上述代码片段的输出是:
2
No statements before case/default(switch constructs): is executed inside switch
现在回答
I don't want to get any of the cases get invoked. But I still need to acces and increment the argument of the switch
只需将 if()
移到 switch() 外面即可。
if (RunIndexSyncedWithADCensured) {
switch (RunIndex++) {
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
/* Other cases here */
default:
RunIndex = 0;
break;
}
} else
RunIndex++;
为什么不先保存值再递增,在开关中使用保存的值呢?顺便说一下,这还包括两次访问,第一次是从 RunIndex 读取值,第二次是递增它。
int runIndex = (RunIndex++);
if (RunIndexSyncedWithADCensured )
{
switch (runIndex)/*RunIndex may only be accessed one time per execution
of this construct and has to be incremented in the same step. thats given.*/
{
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
case 1:
Case1RelatedData = SomeOperationsForCase1(RawData);
break;
case 2:
Case2RelatedData = SomeOperationsForCase2(RawData);
break;
default:
RunIndex = 0;
break;
}
}
由于您使用的是相邻的索引号,因此您可以创建一个函数指针数组来替换开关。这就是优化器无论如何都会将开关变成的东西。因此,您得到的不是晦涩的开关,而是:
if (RunIndexSyncedWithADCensured)
{
SomeOperationsForCase[RunIndex](RawData);
}
RunIndex++;
if (RunIndex > MAX)
{
RunIndex = 0;
}
与switch语句设计完全无关:如果RunIndex
是一个敏感的volatile变量,比如一些硬件寄存器,那么你不应该直接在任何形式的计算中使用它。复制一份:
volatile int RunIndex;
...
int index = RunIndex; // read from RunIndex
if (RunIndexSyncedWithADCensured)
{
SomeOperationsForCase[index](RawData);
}
index++;
if (index > MAX)
{
index = 0;
}
RunIndex = index; // write to RunIndex
这是所有此类易变变量的标准做法。
我正在开发一个嵌入式系统,其中必须访问一个寄存器,然后递增以获得我正在寻找的结果,因为机器正在通知并配置为对我的访问和更改做出反应或不更改标志。所以 switch
的参数必须保持原样,否则它会改变嵌入式系统的行为。
但可能会出现我不想调用任何案例的情况。但是我仍然需要访问并增加 switch
.
(更深入我正在逐步将一系列模拟值转换为数字值转换。索引用于与当前转换保持同步并将其与相应的案例相关联以正确处理数字。有可能会出现索引与当前转换不同步的状态,因此转换序列必须 运行 通过,而不会调用任何情况(以防止设置错误的数据),直到序列完成并且可以重新同步执行)
我目前的做法是这样的:
switch (RunIndex++)/*RunIndex may only be accessed one time per execution
of this construct and has to be incremented in the same step. thats given.*/
{
if (RunIndexSyncedWithADCensured == false)
{
break;
}
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
case 1:
Case1RelatedData = SomeOperationsForCase1(RawData);
break;
case 2:
Case2RelatedData = SomeOperationsForCase2(RawData);
break;
default:
RunIndex = 0;
break;
}
这个构造完成了工作,但它看起来有点争议,考虑将其提交到产品代码中我感觉不太好。
那么有没有更好看的方法来实现相同的目标,而不需要额外的变量或赋值?
注:
这也可能是相关的,它位于由两部分组成的中断函数的第一部分。
第一部分处理必须发生的事情 if()
转换完成。第二部分,还有什么需要做的if()
这个转换也结束了序列。因此,在不进入第二部分的情况下,从函数中简单地 return 是没有选择的。目前还没有 if(...)break;
可能爆发的循环结构。 (这也是我将 if 放在 switch 范围内的原因,因为它至少按照标准是一种有效的突破方式。)
首先,switch()
里面的if()
永远不会被执行。
考虑以下代码片段:
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 2;
switch(i) {
if (i == 2) {
printf("I M HERE\n");
}
case 1:
printf("1\n");
break;
case 2:
printf("2\n");
break;
default:
printf("default\n");
break;
}
return 0;
}
对于您的代码:您希望打印字符串 I M HERE
。但事实并非如此。
上述代码片段的输出是:
2
No statements before case/default(switch constructs): is executed inside switch
现在回答
I don't want to get any of the cases get invoked. But I still need to acces and increment the argument of the switch
只需将 if()
移到 switch() 外面即可。
if (RunIndexSyncedWithADCensured) {
switch (RunIndex++) {
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
/* Other cases here */
default:
RunIndex = 0;
break;
}
} else
RunIndex++;
为什么不先保存值再递增,在开关中使用保存的值呢?顺便说一下,这还包括两次访问,第一次是从 RunIndex 读取值,第二次是递增它。
int runIndex = (RunIndex++);
if (RunIndexSyncedWithADCensured )
{
switch (runIndex)/*RunIndex may only be accessed one time per execution
of this construct and has to be incremented in the same step. thats given.*/
{
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
case 1:
Case1RelatedData = SomeOperationsForCase1(RawData);
break;
case 2:
Case2RelatedData = SomeOperationsForCase2(RawData);
break;
default:
RunIndex = 0;
break;
}
}
由于您使用的是相邻的索引号,因此您可以创建一个函数指针数组来替换开关。这就是优化器无论如何都会将开关变成的东西。因此,您得到的不是晦涩的开关,而是:
if (RunIndexSyncedWithADCensured)
{
SomeOperationsForCase[RunIndex](RawData);
}
RunIndex++;
if (RunIndex > MAX)
{
RunIndex = 0;
}
与switch语句设计完全无关:如果RunIndex
是一个敏感的volatile变量,比如一些硬件寄存器,那么你不应该直接在任何形式的计算中使用它。复制一份:
volatile int RunIndex;
...
int index = RunIndex; // read from RunIndex
if (RunIndexSyncedWithADCensured)
{
SomeOperationsForCase[index](RawData);
}
index++;
if (index > MAX)
{
index = 0;
}
RunIndex = index; // write to RunIndex
这是所有此类易变变量的标准做法。