在switch case语句中声明变量

时间:2020-10-26 12:01:38

标签: c casting switch-statement

我在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

我尝试不使用大括号,也尝试按照一些答案中的分号放置分号。但是它没有被编译。

我如何正确提及变量会因情况而异的数据类型。

3 个答案:

答案 0 :(得分:6)

您声明定义三个局部变量,但在其极小的范围之外没有任何可见的影响。它们分别(即即刻)停止在自己的}上可用。这就是error identifier data is undefined的原因。

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

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

我考虑以上部分,以回答您有关发生的错误的问题,并解决您似乎有的基本误解。下面找到一种替代方法。

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

其他答案显示了基于struct-un-union的解决方案,请看一看。

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

答案 1 :(得分:3)

您的请求有两个问题。

  • 一个是用于说明要限制范围的构造。在C中大括号({...})中定义的变量仅在大括号内有效。这些变量在花括号外将不再有用。
  • Two与One的关系在于,一旦解决了范围问题,由于需要读取不同类型的值,则您的代码必须具有类似类型的变量才能接收它们,因此您会获得一个乘法定义的变量定义问题。尝试创建3个具有相同名称的不同类型的变量将不会编译。

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

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

编辑 解决OP注释:“谢谢您指出,是的,这里有空指针” 。我更改了作业说明以反映此评论。

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;
}

答案 2 :(得分:1)

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

有不同的解决方案,但是在此之前,请检查代码概念的正确性。

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

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;
         ...
 }

或者您可以在开关之前和之后以这种方式检查哪个指针具有值来声明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;
    }  

很显然,您可以根据需要将此重复的代码包装在函数中。