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

how to create a general pointer which can deal with int and double variables and avoid scoping issues?

本文关键字:double 处理 变量 int 问题 范围 创建 何创建 一个 指针      更新时间:2023-10-16

我有一些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语句之外,代码将编译,但if / else内部的M在外部是不同的M

因此,我可以通过定义两个指针(一个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,我该如何解决这个问题,这取决于我的传入数据?我可以用某种指针来解决这个问题吗?我不想为每种情况写重复的代码。

EDIT模板函数或函数重载能解决我的问题吗?我对特定于C/C++的解决方案很灵活

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

在基本级别上,将两个数字相加所需的机器代码对于整数和浮点数是不同的。

这种差异是"隐藏的",因为数据是类型化的,所以编译器总是知道每个操作数的类型,并可以生成正确的代码。

如果你想在运行时之前移动这些信息,编译器就不能再做它的事情了,所以你必须这样做,并确保你的代码采用正确的路径。

您可以尝试使用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("%in", M[0].I); //somefunction(M[0].I);
  } else {
    printf("%lfn", M[1].D); //somefunction(M[1].D);
  }
}

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

顺便说一句:在这种情况下,我更喜欢switchcase而不是if-else,因为它更容易维护,并且可能生成更快的代码。

您可以使用宏,例如:

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

然后在你的另一个代码中:

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

如果您不熟悉do...while(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