2

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.

Zig Razor
  • 3,381
  • 2
  • 15
  • 35
zero cool3
  • 59
  • 5
  • 1
    You cannot. Furthermore the code most probably isn't correct. – Antti Haapala -- Слава Україні Oct 26 '20 at 12:08
  • 2
    Also given the brackets, you would not get the redefinition error either. Please ask about the **actual** problem you're having, not just the supposed solution. – Antti Haapala -- Слава Україні Oct 26 '20 at 12:09
  • I suspect that what you are trying to do is related to this (admittedly an answer of mine): https://stackoverflow.com/questions/58280538/how-to-verify-if-a-void-pointer-void-is-one-of-two-data-types/58281061#58281061 – Yunnosch Oct 26 '20 at 12:12
  • 3
    This: `float * data = (uint32_t*)in_data;` looks very strang. You take something (probably a void pointer!?) and cast it to a uint32_t pointer and assign the result to a float pointer. That's really strange. This also applies to the other cases, i.e. the cast doesn't match the assignment – Support Ukraine Oct 26 '20 at 12:17
  • 1
    What is the actual problem you are trying to solve? Type-generic programming in some manner? What is "in_data" and where does it come from? – Lundin Oct 26 '20 at 12:23
  • 3
    I am with Jabberwocky. However, please be careful not to turn this into a "moving target" question (i.e. edit it to ask a differnt thing which invalidates existing answers). People who created answers do not appreciate that. (And yes, one of them is me....) If you realise that you want to ask a different question, please create a separate new one. – Yunnosch Oct 26 '20 at 12:41
  • @4386427 Thank you for pointing out, yes, There is void pointer . and both sides variable has same data type. – zero cool3 Oct 26 '20 at 13:22
  • It is never a good idea to correct your original post other than for formatting or other readability issues, or to add content that was not there before, usually in response from someone to include it. But never change the existing syntax or construct as these are the very things that are being addressed in answers, and in comments. These changes introduce confusion all around. – ryyker Oct 26 '20 at 13:28
  • @ryyker I will definitely keep this in mind. I am aware that who are all helping , are also occupied and I will take care to not to create confusion from next time onwards. – zero cool3 Oct 26 '20 at 13:32
  • @Yunnosch Yes, I will be careful and will also take great care next time onwards. – zero cool3 Oct 26 '20 at 13:33
  • @ryyker In general I agree with that. But I don't think the code was changed in a way that changed the meaning of the code – Support Ukraine Oct 26 '20 at 13:34
  • After all the edits the code starts making some sense and the answers below apply. – Jabberwocky Oct 26 '20 at 13:35
  • @4386427 - Um, I am a little red faced. After having looked closer at the change, I agree with you. My comment should have been on the order of a bee-bee rather than a Howitzer. Thanks. – ryyker Oct 26 '20 at 13:36

3 Answers3

6

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.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
3

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;
}
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • 2
    `data->iVal = (uint16_t*)in_data;` Hmm... looks strange to me. Assigning a pointer to an int – Support Ukraine Oct 26 '20 at 12:33
  • 1
    well, now we don't know what is being assigned... OPs code is strange an it miss a lot of info. However, from what OP did post, it seems to me that `in_data` is a pointer. – Support Ukraine Oct 26 '20 at 12:37
1

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.

Zig Razor
  • 3,381
  • 2
  • 15
  • 35
  • Hi @Zig Razor : I have tried your first solution (without braises) but it also showing error, the I have looked up threads over here and over internet search and I have applied the braises. – zero cool3 Oct 26 '20 at 13:48