如何创建一个通用指针,它可以处理int和double变量并避免范围问题
how to create a general pointer which can deal with int and double variables and avoid scoping issues?
我有一些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
。
- 警告处理为错误这里有什么问题
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 使用流处理接收到的数据
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 基于多个条件处理地图中的所有元素
- 如何用数字处理log(0)
- SSL上的`curl_easy_send`和`curl_asy_recv`:如何处理`CURLE_AGAIN`
- 错误处理.将系统错误代码映射到泛型
- 从文本文件中读取时钟时间和事件时间并进行处理
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 用于矢量处理的多个线程
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- 当我使用可变参数时,它可以很好地处理int和double,但当涉及到float时,会发生错误
- 如何创建一个通用指针,它可以处理int和double变量并避免范围问题
- C++如何处理 const double&引用 int?
- C++到C#端口的问题:如何处理一个以double*为参数的方法