我在减少for
循环的数量上有问题。它们针对不同类型执行相同的操作。
我应该使用void指针还是其他指针。
是否可以减少代码数量?
void smt(int nb, int iform, void *ptr)//example function
{
int *ipt;// pointers definitions
float *fpt;
double *dpt;
if( iform == 1 )
{
ipt = (int *) ptr;
for( int i = 0; i < nb; i++ )
ipt[i]=i;
}
else if( iform == 2)
{
fpt = (float *)ptr;
for( int i = 0; i < nb; i++)
fpt[i] = 2.71;
}
else
{
dpt = (double *)ptr;
for( int i = 0; i < nb; i++)
dpt[i] = i*3.14159;
}
}
int main(void)
{
int nb = 5;
float iform = 2;
float *a = malloc(nb*sizeof(float)); //allocate memory
float *fpt;
//there should be double *dpt and so on
smt(nb, iform, a );
if( iform == 1)
{
for( int i = 0; i < nb; i++)
printf("a = %d\n", a[i]);
}
else if( iform == 2)
{
for( int i = 0; i < nb; i++)
printf("a = %f\n", a[i]);
}
else
{
for( int i = 0; i < nb; i++)
printf("a = %f\n", a[i]);
}
return 0;
}
答案 0 :(得分:2)
如果您使用以下方式分配内存
float *a = malloc(nb*sizeof(float));
您可以将指针a
用作float数组。编译器知道float
有多大,用于计算数组元素a[i]
的地址。
如果将指针强制转换为其他类型,则数组元素的大小可能会有所不同,从而导致地址不同。使用i != 0
,您将在使用a[i]
或((double*)a)[i]
时将数据存储在不同的地址。
要将不同类型存储在数组中,建议使用union
。建议不要使用iform
的枚举类型来代替#define
的幻数。要减少for循环的次数,您可以将iform
的比较移到循环主体中。
union data {
int intVal;
float floatVal;
double doubleVal;
};
enum dataType {
INT_DATA = 1,
FLOAT_DATA = 2,
DOUBLE_DATA = 3
}
void smt(int nb, enum dataType iform, union data *ptr)//example function
{
for( int i = 0; i < nb; i++ )
{
switch( iform )
{
case INT_DATA:
ptr[i].intVal = i;
break
case FLOAT_DATA:
ptr[i].floatVal = 2.71;
break;
case DOUBLE_DATA:
default:
ptr[i].doubleVal = i*3.14159;
break;
}
}
}
int main(void)
{
int nb = 5;
enum dataType iform = FLOAT_DATA;
union data *a = malloc(nb*sizeof(union data )); //allocate memory
smt(nb, iform, a );
for( int i = 0; i < nb; i++)
{
switch( iform )
{
case INT_DATA:
printf("a = %d\n", a[i].intVal);
break
case FLOAT_DATA:
printf("a = %f\n", (double)a[i].floatVal);
break;
case DOUBLE_DATA:
default:
printf("a = %f\n", a[i].doubleVal);
break;
}
}
return 0;
}
可以使用void指针进行强制转换,但必须将指针用于最大的数据类型,而不是将指针强制转换为数组a
的开始,yopu必须强制转换数组元素的地址。假设double
是最大的数据类型,则您可以执行以下操作。
double *a = malloc(nb*sizeof(*a)); //allocate memory
int *ipt = (int*)&(a[i]);
*ipt = i;
但我不建议这样做。
答案 1 :(得分:0)
由于C不知道模板,人们可能会回退使用预处理器和某些(在?)合理的宏:
#include <stdlib.h>
#include <stdio.h>
#include <math.h> /* for M_PI */
#ifndef M_PI
# define M_PI (3.14159265359)
#endif
#define SMT_INIT(T, p, nb) do { \
(p) = malloc(nb * sizeof (T)); \
} while (0)
#define SMT(T, p, nb, stmt) do { \
for (size_t i = 0; i < (nb); ++i) \
{ \
((T*)(p))[i] = (T)(stmt); \
} \
} while (0)
#define SMT_PRINT(T, p, nb, fmt) do { \
for (size_t i = 0; i < (nb); ++i) \
{ \
printf("%" fmt "\n", ((T*)(p))[i]); \
} \
} while (0)
int main(void)
{
void * p = NULL;
int iform = ...;
size_t nb = ...;
int result = 0;
switch (iform)
{
case 1:
SMT_INIT(int, p, nb);
SMT(int, p, nb, i);
SMT_PRINT(int, p, nb, "d");
break;
case 2:
SMT_INIT(float, p, nb);
SMT(float, p, nb, 2.71);
SMT_PRINT(float, p, nb, "f");
break;
case 3:
SMT_INIT(double, p, nb);
SMT(double, p, nb, i * M_PI);
SMT_PRINT(double, p, nb, "f");
break;
case 4:
result = -1;
break;
}
free(p);
return 0 == result ?EXIT_SUCCESS :EXIT_FAILURE;
}
引入另一个包装其他三个内容的宏可能会更加模糊:
#define SMT_ALL(T, p, nb, stmt, fmt) do { \
SMT_INIT(T, p, nb); \
SMT(T, p, nb, stmt); \
SMT_PRINT(T, p, nb, fmt); \
} while (0)
int main(void)
{
...
switch (iform)
{
case 1:
SMT_ALL(int, p, nb, i, "d");
break;
case 2:
SMT_ALL(float, p, nb, 2.71, "f");
break;
case 3:
SMT_ALL(double, p, nb, i * M_PI, "f");
break;
case 4:
result = -1;
break;
}
...
}