C 如何处理类型在运行时确定的数组的声明和分配?

C 如何处理类型在运行时确定的数组的声明和分配?,c,malloc,type-conversion,C,Malloc,Type Conversion,假设磁盘上有五个二进制文件。这五个文件以二进制格式编码数字序列,但它们都有不同的类型。假设它们是短整数、整数、长整数、浮点数和双整数。我们将让文件中也存储不同数量的数字 现在假设我有一个程序,当执行时,会询问用户 输入要加载的文件名: 用户可以从这五个文件中选择一个。我希望程序将这些文件加载到一个数组中,以便可以执行进一步的计算 我们可以假设存在两个函数:一个返回对文件类型(即短INT、INT、LONG、FLOAT或DOUBLE)进行编码的整数值(称为“getfiletype”),另一个返回文件

假设磁盘上有五个二进制文件。这五个文件以二进制格式编码数字序列,但它们都有不同的类型。假设它们是短整数、整数、长整数、浮点数和双整数。我们将让文件中也存储不同数量的数字

现在假设我有一个程序,当执行时,会询问用户

输入要加载的文件名:

用户可以从这五个文件中选择一个。我希望程序将这些文件加载到一个数组中,以便可以执行进一步的计算

我们可以假设存在两个函数:一个返回对文件类型(即短INT、INT、LONG、FLOAT或DOUBLE)进行编码的整数值(称为“getfiletype”),另一个返回文件中的数字数(例如1000、9338、8131、0等)(称为“getfilesize”)。条目的实际数量可能是数十亿个大数字。如果可能的话,在这个程序中,我想对数组使用相同的名称(比如说“array”),它保存用户选择的任何文件的值。这样我就可以有像这样的积木

N=getfilesize("pickedfile.dat");
for(i=0 ; i<N ; i++ ) {
    doublearray[i]==2.0*(double)array[i]+7.12;
}
N=getfilesize(“pickedfile.dat”);

对于(i=0;i您可以使用
void*
指针来存储指向任何数据类型的指针

int num_elements = getfilesize();
size_t element_size;
switch (getfiletype()) {
    case SHORT_INT: element_size = sizeof(short int); break;
    ...
}
void *array = malloc(num_elements * element_size);

...

void process_doubles(void *array) {
    for(i=0 ; i<getfilesize("pickedfile.dat") ; i++ ) {
    doublearray[i] = 2.0 * ((double *) array)[i] +7.12;
}
int num_elements=getfilesize();
大小元素大小;
开关(getfiletype()){
case SHORT\u INT:element\u size=sizeof(SHORT INT);break;
...
}
void*array=malloc(元素数*元素大小);
...
无效进程\u加倍(无效*数组){

对于(i=0;i您可以使用
void*
指针来存储指向任何数据类型的指针

int num_elements = getfilesize();
size_t element_size;
switch (getfiletype()) {
    case SHORT_INT: element_size = sizeof(short int); break;
    ...
}
void *array = malloc(num_elements * element_size);

...

void process_doubles(void *array) {
    for(i=0 ; i<getfilesize("pickedfile.dat") ; i++ ) {
    doublearray[i] = 2.0 * ((double *) array)[i] +7.12;
}
int num_elements=getfilesize();
大小元素大小;
开关(getfiletype()){
case SHORT\u INT:element\u size=sizeof(SHORT INT);break;
...
}
void*array=malloc(元素数*元素大小);
...
无效进程\u加倍(无效*数组){

对于(i=0;i您的程序可以创建一个静态(或全局)void*数组,该数组将由对getfiletype()或getfilesize()的最新调用填充。然后您必须对其进行适当的强制转换(正如您在示例中专门为加倍所做的那样)。假定您已经解决了文件数据方面的加载问题

尽管这种方法在使用上不是很干净(依赖静态或全局模式会限制您执行不同对话的选择-特别是目前的情况,您必须确保按顺序进行操作)

一个更干净的API可能是这样的:

enum TypeEnum { SHORT_INT, INT, LONG, FLOAT, DOUBLE };
void* getfiledata(char *filename, unsigned int *size, TypeEnum *type);
#define GET_DATA_AND_CAST(filename, array, array_size) \
    do { \
        TypeEnum type; \
        void* arr = getfiledata(filename, array_size, &type); \
        switch(type) { \
            case SHORT_INT: \
                array = (short*)arr; break; \
            case INT: \
                array = (int*)arr; break; \
            case LONG: \
                array = (long*)arr; break; \
            case FLOAT: \
                array = (float*)arr; break; \
            case DOUBLE: \
                array = (double*)arr; break; \
            default: \
                // ASSERT \
        } \
    } while(0)
然后,您可以像这样使用它:

void process_doubles(void *array) {
    double to_conv[];
    unsigned int size;
    GET_DATA_AND_CAST("pickedfile.dat", to_conv, &size);

    for(i=0; i<size; ++i ) {
        doublearray[i] = 2.0 * to_conv[i] + 7.12;
    }
}
void进程\u加倍(void*数组){
双倍到_conv[];
无符号整数大小;
获取数据并进行转换(“pickedfile.dat”、转换和大小调整);

对于(i=0;i您的程序可以创建一个静态(或全局)void*数组,该数组将由对getfiletype()或getfilesize()的最新调用填充。然后您必须对其进行适当的强制转换(正如您在示例中专门为加倍所做的那样)。假定您已经解决了文件数据方面的加载问题

尽管这种方法在使用上不是很干净(依赖静态或全局模式会限制您执行不同对话的选择-特别是目前的情况,您必须确保按顺序进行操作)

一个更干净的API可能是这样的:

enum TypeEnum { SHORT_INT, INT, LONG, FLOAT, DOUBLE };
void* getfiledata(char *filename, unsigned int *size, TypeEnum *type);
#define GET_DATA_AND_CAST(filename, array, array_size) \
    do { \
        TypeEnum type; \
        void* arr = getfiledata(filename, array_size, &type); \
        switch(type) { \
            case SHORT_INT: \
                array = (short*)arr; break; \
            case INT: \
                array = (int*)arr; break; \
            case LONG: \
                array = (long*)arr; break; \
            case FLOAT: \
                array = (float*)arr; break; \
            case DOUBLE: \
                array = (double*)arr; break; \
            default: \
                // ASSERT \
        } \
    } while(0)
然后,您可以像这样使用它:

void process_doubles(void *array) {
    double to_conv[];
    unsigned int size;
    GET_DATA_AND_CAST("pickedfile.dat", to_conv, &size);

    for(i=0; i<size; ++i ) {
        doublearray[i] = 2.0 * to_conv[i] + 7.12;
    }
}
void进程\u加倍(void*数组){
双倍到_conv[];
无符号整数大小;
获取数据并进行转换(“pickedfile.dat”、转换和大小调整);

for(i=0;iC是一种静态类型语言,因此不能在运行时声明类型。必须在编译时指定类型。可以使用的是一个void指针(
void*
)它可以指向任何数据类型。当然,在执行所需的类型转换时需要小心。在C中,不能动态更改数组的基本类型,这不是为此而设计的。基本上,您必须为要处理的每个类型编写一个函数。您可以帮助自己编写一个宏,生成以下10种不同的t函数,但如果您是C的初学者,则不应该这样做。顺便说一句,您的代码片段已经有一个严重的缺陷。请仔细阅读。C是一种静态类型语言,因此您无法在运行时声明类型。必须在编译时指定类型。您可以使用的是一个void指针(
void*
)它可以指向任何数据类型。当然,在执行所需的类型转换时需要小心。在C中,不能动态更改数组的基本类型,这不是为此而设计的。基本上,您必须为要处理的每个类型编写一个函数。您可以帮助自己编写一个宏,生成以下10种不同的t函数,但如果您是C语言的初学者,则不应该这样做。顺便说一句,您的代码片段已经存在严重缺陷。请仔细阅读。