如何创建一个可以处理int和double变量并避免范围问题的通用指针?

时间:2014-10-22 09:50:58

标签: c++ c pointers

我有一些C代码,我需要用一组数据进行一些计算。数据可以是INT或DOUBLE。为了处理不同的数据类型,我考虑使用if / else语句并定义在该语句中保存数据的指针:

/* put values into M, depending on data type*/
if (data_type == 2)
{
    double *M;  
    M = somefunction(DOUBLE);
} else {
    unsigned int *M;
    M = somefunction(UINT16);
}

/* dummy code - usually I do some calculations on M which are data type independent */
for (i=0;i<(10);i++) {
    M[i]=0;
}

这会导致范围问题,因为M未在if / else构造之外定义:

 error: ‘M’ undeclared (first use in this function)

如果我将M的定义移到if / else语句之外,代码将会编译,但M内的if / elseM不同。

所以我可以通过定义两个指针,一个double和一个int来解决问题,并检查我的代码中的所有类型,我处理的是:

double *Mdouble;  
unsigned int *Mint;
/* put values into M, depending on data type*/
if (data_type == 2)
{
    Mdouble = somefunction(DOUBLE);
} else {
    Mint = somefunction(UINT16);
}

/* dummy code - usually I do some calculations on M which are data type independent */
for (i=0;i<(10);i++) {
    if (data_type == 2) {
        Mdouble[i]=0;
    } else {
        Mint[i]=0;
    } 
}

所以这是我的问题:

如果M是double或int,我该如何解决这个问题,具体取决于我的传入数据?我可以通过指向指针的某种指针来解决这个问题吗?我不想为每个案例编写重复的代码。

编辑可以模板功能重载功能解决我的问题?我对C / C ++特定解决方案非常灵活

5 个答案:

答案 0 :(得分:3)

您将不得不编写重复的代码。

在基本级别,添加两个数字所需的机器代码对于整数与浮点数不同。

由于数据是类型化的,因​​此这种差异是“隐藏的”,因此编译器始终知道每个操作数的类型,并且可以生成正确的代码。

如果要将该信息移动到运行时,编译器就无法再执行此操作,因此您将不得不这样做,并确保您的代码采用正确的路径。

答案 1 :(得分:2)

您可以尝试使用C联合:

#include <string.h>
#include <stdio.h>

int main(int argc, char** argv) {
  union MyUnion {
    int I;
    double D;
  };
  union MyUnion M[10];
  // Initializing the array to 0 (data type independent)
  memset(M, 0, 10*sizeof(MyUnion));
  M[0].I = 1;
  M[1].D = 1.5;
  if (argc==1) { // It should be "if (data_type==2) {"
                 // but I wanted an example that compiles easily
    printf("%i\n", M[0].I); //somefunction(M[0].I);
  } else {
    printf("%lf\n", M[1].D); //somefunction(M[1].D);
  }
}

答案 2 :(得分:1)

在C中你必须使用宏

int8_t* ptr=...;
while(n)
    {
    switch(data_type)
        {
        case TYPE_DOUBLE:
            A_MACRO_THAT_DEFINES_YOUR_OPERATION((double*)ptr);
            ptr+=sizeof(double);
            break;
        case TYPE_INT:
            A_MACRO_THAT_DEFINES_YOUR_OPERATION((int*)ptr);
            ptr+=sizeof(int);
            break;
        }
    --n;
    }

这个解决方案很慢,因为它需要测试每个元素的数据类型。您可以将整个循环写为宏。这会更快但更难阅读。

如果您可以使用C ++,请改用模板。以下是使用模板的解决方案:

template<class T>
void doStuff(T* ptr_begin,T* end)
    {
    while(ptr_begin!=ptr_end)
        {
   //   Do stuff
        ++ptr_begin;
        }
    }

void doStuffWrapper(void* ptr_begin,void* ptr_end,uint32_t type)
    {
    switch(type)
        {
        case TYPE_DOUBLE:
            doStuff((double*)ptr_begin,(double*)ptr_end);
            break;
        case TYPE_INT:
            doStuff((int*)ptr_begin,(int*)ptr_end);
            break;
        }
    }

作为旁注:在这种情况下,我更喜欢使用if-else的switch-case,因为它更容易维护,并且可能产生更快的代码。

答案 3 :(得分:0)

您可以使用宏,例如:

#define CALCULATIONS(M) do { \
    for (i=0;i<(10);i++) \
        (M)[i]=0; \
    } while (0)

然后在你的其他代码中:

if ( data_type == 2 )
{
    double *M = whatever;
    CALCULATIONS(M);
}

See here如果您不熟悉do...while(0)技术

答案 4 :(得分:0)

听起来你想要一个模板化的功能。

但我认为问题归结为,你能把所有的工作都放在这个功能中吗?

template <typename T>
T* somefunction(T data){
    //start old somefunction code
    T* result = new T[10]{data, data, data, data, data, data, data, data, data, data};
    //end old somefunction code

    //begin "calculations on M which are data type independent"
    for(int i = 0; i < 10; i++){
        M[i] = 0;
    }
    return M;
}

因此,使用上述代码,您可以执行double* Mdouble = somefunction(13.13)short* Mshort = somefunction(13);

最好的情况是M实际上是一个抛弃数组,在这种情况下你甚至可以在模板函数的堆栈框架中分配数据并避免使用new