【问题标题】:declaration of variable inside switch case statement在 switch case 语句中声明变量
【发布时间】:2020-10-26 12:01:38
【问题描述】:

我在 C 中的代码具有如下 switch case 语句。

float value_calc ( Type_t type, void *in_data)
{
     switch ( type)
     {
          case 0:
          {
            int * data = (int*)in_data;
          }
          break;
          case 1:
          {
           float * data = (float*)in_data;
          }
          break;   <-- error :- data: redefinition; different basic types.  
          case 3:
          {
            double * data = (double*)in_data;
          }
          break;
          default:
                return 0;
       }
      for (int i =0; i< 1024; i++)
      {
          float capture = * (data + i) + diff; <-- error identifier data is undefined
      }                

这里,Type_t 是枚举,其数据类型为 int =0 作为第一个成员,其他成员依次是 floatdouble

我已经尝试不使用花括号,并且还按照这里提到的在一些答案中放置分号。但它没有被编译。

我如何正确提及变量将根据情况使用不同的数据类型。

【问题讨论】:

  • 你不能。此外,代码很可能不正确。
  • 同样给定括号,你也不会得到重新定义错误。请询问您遇到的实际问题,而不仅仅是假设的解决方案。
  • 这个:float * data = (uint32_t*)in_data; 看起来很奇怪。你拿了一些东西(可能是一个空指针!?)并将其转换为一个 uint32_t 指针并将结果分配给一个浮点指针。这真的很奇怪。这也适用于其他情况,即演员表与分配不匹配
  • 您要解决的实际问题是什么?以某种方式进行泛型编程?什么是“in_data”,它来自哪里?
  • 我和 Jabberwocky 在一起。但是,请注意不要将其变成“移动目标”问题(即编辑它以询问使现有答案无效的不同事物)。创造答案的人并不欣赏这一点。 (是的,其中一个就是我......)如果你意识到你想问一个不同的问题,请创建一个单独的新问题。

标签: c casting switch-statement


【解决方案1】:

您声明定义了三个局部变量,在它们极小的范围之外没有任何可见的影响。它们分别在自己的} 上不再可用,即立即。这就是为什么error identifier data is undefined

顺便说一下,这些小范围是您可以编译第一个代码片段的唯一原因,否则这些定义会在同一范围内以不同类型定义相同标识符时发生冲突。

您稍后会尝试在运行时将标识符 data 与不同的类型一起使用。
你不能。

我认为上述部分是为了回答您关于发生错误的问题,并解决您似乎有的基本误解。下面找到一种方法的替代想法。

这可能需要重新设计。 (数据指针指向的)类型会影响程序在引用指针时如何处理它找到的内容。您显示的循环似乎依赖于通过指针类型选择该处理。您需要更明确地使用指针在运行时更改类型,因为在 C 中指针变量不能这样做。

其他答案显示基于 struct-with-union 的解决方案,看看它们。

但是,我认为值得退后一步并重新考虑更大的范围(即我怀疑这里存在 XY 问题...)。
如果您可以使用Type_t type 参数携带的信息并选择相应的处理方法,然后可以“感知”指向的类型,事情会容易得多。
这基本上意味着将 switch 语句放入循环中,或者将循环放入 switch 语句中。因为我猜您正在寻找速度,所以您应该同时尝试并计时。

【讨论】:

    【解决方案2】:

    您的请求有两个问题。

    • 一个是您用来说明您想要做什么的结构是范围限制。 C 中花括号 ({...}) 中定义的变量仅在花括号内有效。然后这些变量在花括号之外就没有用了。
    • Two 与 One 相关,因为一旦您解决了范围问题,您就会遇到多重定义的变量定义问题,因为需要读取不同类型的值,您的代码必须具有类似类型的变量才能接收它们。尝试创建 3 个不同类型的同名变量将无法编译。

    因此,使用该构造不是一种选择。但是,通过对现有构造进行一些调整并引入新构造,可能会有一种方法可以满足您的需求。

    下面是一个简单的插图,展示了我将如何解决这些问题。使用struct(){...}union(){...} 成员(也许是指针,也许不是)的某种形式将有助于解决范围和变量定义问题。以下变化可以适应您的特定需求。 (即是否使用指针。)

    编辑以解决 OP 评论:“感谢您指出,是的,有 void 指针”。我更改了赋值语句以反映此评论。

    typedef union  {
        int *iVal;//assuming code will assign from void * (3 places)
        float *fVal;
        double *dVal;
    }types_u; 
    
    typedef struct {
        types_u *types;
        int type;
    }data_s;
    
    //for readability in the using code, define human readable types
    enum {
        _INT_,
        _FLOAT_,
        _DOUBLE_
    };
    
    #define DATA_SIZE 1024
    
    //for testing code: (un-comment one type and the void *)
    //int v = 10; 
    //float v = 10.0;
    //double v = 10.0;
    //void *in_data = &v;
    
    int main(int argc, char *argv[]) 
    {
        
        data_s *data = malloc(DATA_SIZE*sizeof(*data));
        if(data)
        {
            memset(data, 0, sizeof(*data)*DATA_SIZE);
            //for testing code:
            data[0].type = _INT_;
    
            
            for(int i=0;i<DATA_SIZE;i++)
            {
                switch(data[i].type)
                {
                     case _INT_:
                         data[i].types.iVal = (int *)in_data;
                         break;
                     case _FLOAT_:
                         data[i].types.fVal = (float *)in_data;
                         break;
                     case _DOUBLE_:
                         data[i].types.dVal = (double *)in_data;
                         break;
                     //...
                }
            }
            free(data);
        }
        return 0;
    }
    

    【讨论】:

    • data-&gt;iVal = (uint16_t*)in_data; 嗯...对我来说看起来很奇怪。分配一个指向 int 的指针
    • 好吧,现在我们不知道分配了什么... OPs 代码很奇怪,它错过了很多信息。但是,从 OP 发布的内容来看,在我看来 in_data 是一个指针。
    【解决方案3】:

    问题是你在开关的范围内声明了一个局部变量,所以在外面你看不到它。

    有不同的解决方案,但在此之前检查你的代码想法的正确性。

    在任何情况下,每次使用时都可以使用 union 和 swith case:

    typedef union  {
            int* iVal;
            float* fVal;
            double* dVal;
    }data_u;
    data_u *data;
    
     ...
     switch(type)
     {
         case 0:
             data->iVal = in_data;
             break;
         case 1:
             data->fVal = in_data;
             break;
         case 2:
             data->dVal = in_data;
             break;
             ...
     }
    

    或者你可以在 switch 之前声明 n 个指针,然后以这种方式检查哪个有值:

    int* iVal = null;
    float* fVal = null;
    double* dVal = null;
    
    switch(type)
     {
         case 0:
             iVal = in_data;
             break;
         case 1:
             fVal = in_data;
             break;
         case 2:
             dVal = in_data;
             break;
             ...
     }
     
    if (iVal){
    ...
    }else if(fval){
    ...
    }else if(dVal){
    ...
    }else{
    //ERROR
    }
    

    另一种解决方案是将使用此变量的代码放在 switch 的情况下:

    switch ( type)
        {
        case 0:
        {
            int * data = (uint16_t*)in_data;
            for (i =0; i< 1024; i++)
            {
                 float capture = * (data + i) + diff;
            }
        }
        break;
        case 1:
        {
            float * data = (uint32_t*)in_data;
            for (i =0; i< 1024; i++)
            {
                 float capture = * (data + i) + diff;
            }
        }
        break;   <-- error :- data: redefinition; different basic types.  
        case 3:
        {
            double * data = (float*)in_data;
            for (i =0; i< 1024; i++)
            {
                 float capture = * (data + i) + diff;
            }
        }
        break;
        default:
                return 0;
        }  
    

    如果你愿意的话,显然你可以将这个重复的代码包装在一个函数中。

    【讨论】:

    • 嗨@Zig Razor:我已经尝试了你的第一个解决方案(没有braises),但它也显示错误,我已经在这里和互联网搜索中查找了线程并且我已经应用了braises。跨度>
    猜你喜欢
    • 2020-12-27
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 2021-12-05
    • 2016-06-15
    • 1970-01-01
    • 2021-11-24
    相关资源
    最近更新 更多