C 比“如果”更好的解决方案?

C 比“如果”更好的解决方案?,c,embedded,C,Embedded,我必须根据一个大数字的值做一些事情,比如83025(大于65535)。为此,我不能使用switch case,因为它只使用最大值为255的整型参数。(或者至少我是这样知道的。我仍然尝试过,但是它编译了,但是switch案例没有很好地工作。) 所以我想我会做一个if-else-if梯子,像下面这样,但看起来不太优雅 if ((refnum == 32120) || (refnum == 32075)) { else if (refnum == 51036)

我必须根据一个大数字的值做一些事情,比如83025(大于65535)。为此,我不能使用switch case,因为它只使用最大值为255的整型参数。(或者至少我是这样知道的。我仍然尝试过,但是它编译了,但是switch案例没有很好地工作。)

所以我想我会做一个
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
    ,然后
    返回一个特定的值

  • 代码嵌入并在16位微控制器上运行


    • 在这种情况下,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语句(如我的例子中的
      case 0
      case 1
      ),它们的作用类似于

      GCC扩展还允许您以以下方式编写交换机:

      switch (refnum) {
           case 36371 ... 36374:
              //Do the job when refnum is >= 36371 && refnum <= 36374
              break;
      }
      
      开关(refnum){
      判例36371…36374:
      
      //当refnum>=36371&&refnum时执行此操作。您可以创建一个全局数组,其中包含要检查的所有值。只需循环设置此数组。如果您需要为每个数组指定特定行为,请创建一个结构数组并使用函数指针设置不同的行为

      下面是一个例子:

      // 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();
            }
        }
      }
      
      //用于int变量
      #包括
      //用于printf
      #包括
      #定义值_至_猜测3
      #定义NB_值4
      #定义我的\u值\u 1
      #定义我的\u值\u 2
      #定义我的\u值\u 3
      #定义我的\u值\u 4
      无效行为_1(无效){
      printf(“行为1!\n”);
      }
      空洞行为_2(空洞){
      printf(“行为2!\n”);
      }
      空洞行为_3(空洞){
      printf(“行为3!\n”);
      }
      空洞行为_4(空洞){
      printf(“行为4!\n”);
      }
      //使用函数指针定义结构
      类型定义结构s_比较{
      uint32\u t值要进行比较;
      无效(*ptr)(无效);
      }比较;
      //设置我的结构
      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 i=0;i
      如果你需要关于这个的解释,请随时告诉我。 这需要一点设置,但它是解决问题的强大解决方案,而且比if/else/else-if树更优雅

      必须根据一个大数字的值做一些事情,比如83025

      然后确保所有涉及的变量都使用
      uint32\u t

      为此,我不能使用switch case,因为它只使用最大值为255的整数参数

      这是一个误解,不知道你是从哪里得到这个想法的。
      switch
      语句适用于所有整数常量表达式。switch语句本身没有数字限制

      (实际上,switch语句的控制表达式被隐式提升为
      int
      ,如果它恰好是较小的整数类型。)

      所以我想我会做一个像下面这样的“如果-如果-如果-如果”梯子,但它看起来不太优雅。你能确认这是正确的方法吗?或者你有更好的主意吗

      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?
      DWORD
      ?这是Windows编程中的一些难闻的类型,在嵌入式系统中绝对应该避免。使用stdint.h中的类型,而不是一些丑陋的自制类型

      我必须根据一个大数字的值做一些事情,比如83025(大于65535)。为此,我不能使用switch case,因为它只使用最大值为255的整数参数(或者至少我是这样知道的)

      您的理解不正确:以下是C标准的措辞:

      6.8.4.2
      开关
      语句

      switch语句的控制表达式应为整数类型

      […]每个
      case
      标签的表达式应为整数常量表达式,同一
      switch
      语句中的
      case
      常量表达式在转换后不得有相同的值。[…]

      对控制表达式执行整数提升。每个
      大小写
      标签中的常量表达式转换为控制表达式的提升类型。如果转换后的值与提升后的控制表达式的值匹配,则控制跳到匹配的
      大小写
      标签后面的语句。[…]

      因此,一般情况下,案例值在
      65535
      处没有限制,最大值至少为
      18446744073709551615int 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 ) ;
              }
          }
      }