Неспособность использовать массив указателей в C - PullRequest
2 голосов
/ 13 июня 2019

Я пытаюсь создать массив указателей, который будет использоваться как массив данных различных типов.

Здесь я создал массив arr для хранения 5 указателей, каждый из которых указывает на свою переменную. a - это int, b - это float, c - это char, d - это string, fun - это function.

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

void fun(){
    printf("this is a test function");
}

int main() {
    int *arr[5];
    int a = 10;
    float b = 3.14;
    char c = 'z';
    char d[] = "hello";
    arr[0] = &a;
    arr[1] = &b;
    arr[2] = &c;
    arr[3] = &d;
    arr[4] = &fun;

    printf("a : %d\n", *arr[0]);
    printf("b : %d\n", *arr[1]);
    printf("c : %d\n", *arr[2]);
    printf("d : %d\n", *arr[3]);
    *arr[4];

    return 0;
}

Я пытаюсь заставить его распечатать значения a, b, c и d, а затем выполнить функцию fun. Однако я получаю сообщения об ошибках типа:

warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
     arr[1] = &b;

для arr[1], arr[2], arr[3] и arr[4].

Пояснение: я пытаюсь сделать массив (или, после всех комментариев и ответов на данный момент, тип объекта, такой как структура или объединение), способный содержать объекты различных типов данных, включая переменные, функции, структуры и т. Д. Данные типы предполагаются известными. Я просто хочу хранить разные типы данных и использовать их в одном объекте, например в массиве.

Ответы [ 4 ]

2 голосов
/ 13 июня 2019

Это то, что вам нужно сделать:

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

void fun(){
    printf("this is a test function");
}

int main() {
    void *arr[5];
    int a = 10;
    float b = 3.14;
    char c = 'z';
    char d[] = "hello";
    arr[0] = &a;
    arr[1] = &b;
    arr[2] = &c;
    arr[3] = &d;
    arr[4] = fun;

    printf("a : %d\n", *((int *) arr[0]));
    printf("b : %f\n", *((float *) arr[1]));
    printf("c : %c\n", *((char *) arr[2]));
    printf("d : %s\n", (char *) arr[3]);

    void (*f)() = arr[4];
    f();

    return 0;
}

arr - это массив 5 указателей на void (или что угодно). При печати элементов вы должны приводить их к типам, которыми они на самом деле являются. Например, arr[3] - это указатель на массив (поскольку вы берете адрес d). Поскольку адрес первого элемента совпадает с началом массива, мы можем привести его к указателю на char перед печатью.

Для функции (обратите внимание, что просто использование fun даст вам адрес функции), я назначил адрес f, который является указателем на функцию, принимающую неопределенный список аргументов и возвращающую void , Тогда вы можете вызвать f().

Это суть. Прочитайте хорошую книгу для получения дополнительной информации.

1 голос
/ 13 июня 2019

Это может быть возможным вариантом использования для объединения, которое позволит вам хранить указатели на разные типы:

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

void fun(){
    printf("this is a test function");
}

union u {
    int *i;
    float *f;
    char *c;
    char *s;
    void (*fn)();
};

int main() {
    union u arr[5];
    int a = 10;
    float b = 3.14;
    char c = 'z';
    char d[] = "hello";
    arr[0].i = &a;
    arr[1].f = &b;
    arr[2].c = &c;
    arr[3].s = &d;
    arr[4].fn = &fun;

    printf("a : %d\n", *arr[0].i);
    printf("b : %f\n", *arr[1].f);
    printf("c : %c\n", *arr[2].c);
    printf("d : %s\n", arr[3].s);
    (*arr[4].fn)();

    return 0;
}

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

0 голосов
/ 13 июня 2019

Вы можете изменить int *arr[] на void *arr[], это будет работать во время уровня назначения, но когда вы печатаете, вы не можете привести void к int, оно выдаст ошибку.

0 голосов
/ 13 июня 2019

Нельзя назначить целочисленный указатель на адрес переменной, отличной от целочисленного типа данных.

Вы можете изменить тип данных всех переменных на целочисленный тип данных или использовать универсальный указатель для работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...