Приведите void указатель к double, не зная его типа в C - PullRequest
0 голосов
/ 01 мая 2019

Мне нужно написать функцию, которая принимает в качестве параметров указатель void (представляющий массив) и целое число, которое представляет длину массива. В функции мне нужно привести этот пустой указатель в двойной. Проблема в том, что указатель void может представлять массив целых чисел, или чисел с плавающей запятой, или двойных. Таким образом, следующее явно не работает, если указатель void представляет массив целых чисел или чисел с плавающей точкой:

void foo(void *v,int n){
    double *values;

    values=(double*)v;
    for(i=0;i<n;i++)
        printf("%f\n",values[i]);
}

, поэтому вы получите правильный вывод:

foo((double[]){1,2,3,4},4);

и это выведет неверный вывод:

foo((int[]){1,2,3,4},4);
foo((float[]){1,2,3,4},4);

Итак ... могу ли я правильно привести указатель void к двойному, только зная, что это может быть массив целых чисел, чисел с плавающей запятой или двойных чисел? И нужно ли иметь длину массива или я могу как-то рассчитать? Постскриптум без использования обратных вызовов

1 Ответ

0 голосов
/ 01 мая 2019

Могу ли я правильно привести пустой указатель к двойному, зная, что это может быть массив целых чисел, или чисел с плавающей запятой, или двойников?

Нет, вы не можете. Вам нужно как-то передать информацию о типе.

И нужно ли иметь длину массива или я могу как-то рассчитать?

Необходимо передать длину.


Вы можете "скрыть" информацию внутри структуры

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

enum etype { INTEGER, FLOAT, DOUBLE };
struct data {
    void *values;
    size_t n;
    enum etype type;
};

void foo(struct data *x) {
    int *xd = x->values;
    float *xf = x->values;
    double *xg = x->values;
    for (int k = 0; k < x->n; k++) {
        switch (x->type) {
            default: printf("%g ", xg[k]); break;
            case FLOAT: printf("%f ", xf[k]); break;
            case INTEGER: printf("%d ", xd[k]); break;
        }
    }
    puts("");
}

int main(void) {
    struct data x;

    x.values = malloc(4 * sizeof(int));
    ((int*)(x.values))[0] = 42;
    ((int*)(x.values))[1] = -1;
    ((int*)(x.values))[2] = 0;
    ((int*)(x.values))[3] = 999;
    x.n = 4;
    x.type = INTEGER;
    foo(&x);

    x.values = calloc(4, sizeof(float));
    x.type = FLOAT;
    float tmp = 3.14159;
    memcpy(((float*)(x.values))+1, &tmp, sizeof (float));
    foo(&x);
    free(x.values);

    x.values = calloc(4, sizeof(double));
    x.type = DOUBLE;
    ((double*)(x.values))[2] = 2.7182818;
    foo(&x);
    free(x.values);
}

См. код, работающий на ideone

...