declaration of variable inside switch case statement

Viewed 169

I have code in C having switch case statement as below.

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
      }                

here, Type_t is enum having data type int =0 as first member and other member in sequence are float and double.

I have tried without curly braces and also by putting semi-colon as per mentioned here in some answers. But it is not getting compiled.

How do I correctly mention as the variable will different data type as per case.

3 Answers

You declare define three local variables without any visible effect outside of their extremely small scopes. They stop being useable at their own } repectively, i.e. immediatly. That is why error identifier data is undefined.

These small scopes are by the way the only reason why you can compile the first code fragment, these definitions would otherwise clash on defining the same identifier inside the same scope with different types.

You are later trying to use the identifier data with at runtime different types.
You can't.

I consider the above part to answer your questio about the occurring error and also to address the basic misconception you seem to have. Below find an alternative idea for an approach.

This probably requires a little redesign. The type (of what the data pointer is pointing to) influences how the program handles what it finds when deferencing the pointer. The loop you show seems to rely on selecting that handling via the pointers type. You need to do that more explicitly with a pointer which does/can not change the type at runtime, simply because in C pointer-variables cannot do that.

The other answers show struct-with-union based solutions, have a look at them.

I think however that it would be worth to take a step back and reconsider on a larger scope (i.e. I suspect there is a XY problem here...).
Things would be much easier if you could use the info carried by the Type_t type parameter and select according methods for processing, which can then be "aware" of the pointed-to-type.
This basically mean to put the switch statement into the loop, or the loop into the switch statement. Because I guess that you are looking for speed you should try both and time them.

There are two problems with your request.

  • One is the construct you use to illustrate what you want to do is scope limiting. Variables defined within curly braces ( {...} ) in C have life only within the braces. These variable then will not be useful outside their curly braces.
  • Two is related to One in that once you have addressed your scope problem, you gain a multiply defined variable definition problem due to the requirement that reading in values of differing types, your code must have variables of like types to receive them. Attempting to create 3 differently typed variables with the same name will not compile.

So then, using that construct is not an option. However, with some adjustments to the existing construct, and the introduction new constructs, there may be a way to do what you need.

The following is simple an illustration showing how I would address these issues. Using some form a struct(){...} with a union(){...} member (perhaps a pointer, perhaps not) will help to address both the scope and variable definition problem. Variations of the following can be adapted to your specific needs. (i.e. whether you use pointers or not.)

EDIT to address OP comment: "Thank you for pointing out, yes, There is void pointer". I changed the assignment statements to reflect this comment.

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

The problem is that you declare a local variable inside the scope of the switch so outside you can't see it.

There are different solution, but before this check the correctness of the idea of your code.

In any case you can use union and swith case every time you use it:

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

or you can declare n pointers before the switch and after check which one has value in this way:

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
}

Another solution is to put the code that use this variable inside the case of 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;
    }  

Obviously youy can wrap this repeated code in a function if you want.

Related