我必须根据像83025(大于65535)这样的大数字的值来做一些事情。为此,我不能使用switch-case,因为它只使用最大值为255的整数参数。(或者至少这是我所知道的。但我仍然尝试过编译,但是switch-case不起作用好。)
所以我想我会在下面制作一个if-else if
梯子,但看起来并不太优雅。
if ((refnum == 32120) ||
(refnum == 32075)) {
else if (refnum == 51036) {
else if ((refnum == 61024) ||
(refnum == 61060)) {
else if ((refnum == 71030) ||
(refnum == 71048)) {
else if ((refnum == 72012) ||
(refnum == 72024) ||
(refnum == 72048)) {
else if ((refnum == 81025) ||
(refnum == 81050) ||
(refnum == 81100)) {
else if ((refnum == 82012) ||
(refnum == 82024) ||
(refnum == 82048) ||
(refnum == 82096)) {
else if ((refnum == 83050) ||
(refnum == 83100)) {
您能否确认这是正确的方法?或者你有更好的主意吗?
其他信息:
refnum是一个32位无符号整数
大号来自字符串的中间,strtol
将其转换为DWORD
在每种情况下我必须做的事情是执行strcpy
然后return
某个值。
代码嵌入并在16位微控制器上运行
答案 0 :(得分:7)
必须根据像83025这样的大数字的值来做一些事情
然后确保所涉及的所有变量都使用uint32_t
。
为此,我不能使用switch-case,因为它只使用最大值为255的整数参数
这是一个误解,不确定你从哪里得到这个想法。 switch
语句适用于所有整型常量表达式。 switch语句本身没有数字限制。
(实际上,switch语句的控制表达式被隐式提升为类型int
,如果它恰好是一个较小的整数类型。)
所以我想我会在下面做一个if-else if ladder,但它看起来并不太优雅。你能否证实这是正确的做法?或者你有更好的主意吗?
if-else会生成与相应交换机完全相同的机器代码。这个开关可能会增加一点可读性,因此可能是一个更好的选择:
switch (refnum)
{
case 32120: do_this(); break;
case 61024: do_that(); break;
...
default: do_something();
}
替代:
我注意到这些是按排序顺序排列的整数值。如果有很多值或需要快速查找,您也可以用二进制搜索替换整个事物。这可能会提供更快的代码,但也会增加复杂性。最好使用C标准bsearch()
。
但是,如果您希望最终实现的是返回指向字符串的指针,那么此解决方案可能是理想的。然后,您可以将数字和字符串存储为键值对:
typedef struct
{
uint32_t key;
const char* str;
} thingie_t;
static const thingie_t things [] =
{
{ 32120, "text string" },
{ 32075, "another text string" },
...
};
大数字来自字符串的中间,strtol将其转换为DWORD
为什么使用签名号码?数据似乎没有签名。什么是DWORD
?这是Windows编程中的一些臭类型,在嵌入式系统中肯定应该避免。使用stdint.h中的类型,而不是一些丑陋的自制类型。
答案 1 :(得分:4)
我必须根据83025这个大数字的值来做一些事情(大概是65535)。为此,我不能使用switch-case,因为它只使用最大值为255的整数参数。(或者至少这是我所知道的。)
您的理解不正确:以下是C标准的措辞:
6.8.4.2
switch
声明switch语句的控制表达式应为整数类型。
[...]每个
case
标签的表达式应为整数常量表达式,同一case
语句中的switch
个常量表达式中没有两个具有相同的值转换后。 [...]对控制表达式执行整数提升。每个
case
标签中的常量表达式将转换为控制表达式的提升类型。如果转换后的值与提升的控制表达式匹配,则控制将跳转到匹配的case
标签后面的语句。 [...]
因此,对于案例值,65535
一般没有限制,如果18446744073709551615
表达式的类型为switch
,则最大值至少为unsigned long long
。如果您的switch
表达式是unsigned int
并且您的目标平台具有16位整数,则案例表达式的最大值将为65535
,但是根据您要测试的值,{ {1}}的类型必须大于此类型。
然而我仍然尝试编译,但是切换案例效果不佳。
你没有发布有问题的代码......除非你的编译器很古老或严重破坏,否则问题不在你怀疑的地方,更可能是代码中的错误。
来自提供的额外信息 编辑,目标平台确实有16位refnum
,但int
必须大于refnum
或{{1}容纳大于int
的值,unsigned int
或65535
。然后,编译器应接受大于long
的{{1}}值。古代编译器可能不符合这一点......在这种情况下,您可能会遇到更多问题。
答案 2 :(得分:3)
在这种情况下,Switch语句可以为您完成工作。
switch (refnum) {
case 0:
case 1:
//Do stuff when refnum is 0 or 1
break;
case 2:
//Do stuff when refnum is 2
break;
case 36371:
case 36372:
case 36373:
case 36374:
// if (refnum == 36371 || refnum == 36372 || refnum == 36373 || refnum == 36374)
break;
default: break;
}
美丽是您可以在if语句中应用多个案例陈述(例如case 0
和case 1
),其行为与or
相同。
GCC扩展还允许您以这种方式编写交换机:
switch (refnum) {
case 36371 ... 36374:
//Do the job when refnum is >= 36371 && refnum <= 36374
break;
}
但请记住!这并非在所有编译器中都可用。
答案 3 :(得分:1)
您似乎拥有非常严格的非标准编译器。
您可以为每个动作创建一个函数,然后生成一个refnum到函数指针的查找表并扫描它。例如:
int action1( unsigned long refnum ) ;
int action2( unsigned long refnum ) ;
int action3( unsigned long refnum ) ;
int action4( unsigned long refnum ) ;
int action5( unsigned long refnum ) ;
...
int action8( (unsigned long ) ;
int doRefnumAction( unsigned long refnum )
{
typedef void(*refnumFn)(unsigned long ) ;
static const struct
{
unsigned long refnum,
refnumFn refnum_action
} refnum_lookup[] = { {32120, action1}, {32075, action1},
{51036, action2},
...
{82012, action7}, {82024, action7}, {82048, action7}, {82096, , action7},
{83050, action8}, {83100, action8} } ;
// Find refnum in lookup and call action...
for( int i = 0 ;
i < sizeof(refnum_lookup) / sizeof(*refnum_lookup) ;
i++ )
{
if( refnum == refnum_lookup[i].refnum )
{
return refnum_lookup[i].refnum_action( refnum ) ;
}
}
}
是否更好以任何方式if-else if
解决方案可能是意见问题,代码空间术语可能更大,执行速度更慢但可以更容易维护。
答案 4 :(得分:0)
一旦我们了解了编译器和真实代码的详细信息,我们就可以找出您认为不能使用switch语句的原因。在那之前,每个人都在猜测。
多年来我使用了大量的C编译器,从未听说过用这种方式限制开关的编译器。这听起来像是20世纪90年代存在于8位微控制器中的伪C编译器 - 这不是你今天看到的。
如果您使用的是合适的编译器,并且启用了优化,则开关将是最快的方式。有人提到二进制搜索是一个更复杂但更快的解决方案 - 一个好的编译器会自动从switch语句生成跳转表或二进制搜索,以便为您提供最有效的代码。
答案 5 :(得分:-1)
您可以创建一个包含要检查的所有值的全局数组。并简单地循环这个数组。如果你可以创建一个struct数组并使用函数指针来设置不同的行为,那么如果你需要为每个其他人提供特定的行为。
以下是一个例子:
// For int variables
#include <stdint.h>
// For printf
#include <stdio.h>
#define VALUE_TO_GUESS 3
#define NB_VALUES 4
#define MY_VALUE_1 1
#define MY_VALUE_2 2
#define MY_VALUE_3 3
#define MY_VALUE_4 4
void behavior_1(void) {
printf("Behavior 1 !\n");
}
void behavior_2(void) {
printf("Behavior 2 !\n");
}
void behavior_3(void) {
printf("Behavior 3 !\n");
}
void behavior_4(void) {
printf("Behavior 4 !\n");
}
// Definition of the struct using a function pointer
typedef struct s_compare {
uint32_t value_to_compare;
void (*ptr)(void);
}t_compare;
// Setting up my struct
t_compare g_compare[] = {
{MY_VALUE_1, behavior_1},
{MY_VALUE_2, behavior_2},
{MY_VALUE_3, behavior_3},
{MY_VALUE_4, behavior_4}
};
int main(void) {
for (int i = 0; i < NB_VALUES; i++) {
/* If your current value match the value set in the current struct
then call the function pointer associated, with these 2 lines i can
compare an infinite quantity of numbers */
if (g_compare[i].value_to_compare == VALUE_TO_GUESS) {
g_compare[i].ptr();
}
}
}
如果您需要有关此问题的解释,请随时告诉我。 这需要一些设置,但它是一个功能强大的解决方案,比if / else / else if树更优雅的解决方案。