3

I'm trying to create an array of pointers which is to be used as an array of different data types.

Here, I've created the array arr to hold 5 pointers, each of which points to a different variable. a is an int, b is a float, c is a char, d is a string, fun is a 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;
}

I'm trying to get it to print out the values of a, b, c, and d, then execute the function fun. However, I'm getting errors like:

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

for arr[1], arr[2], arr[3], and arr[4].

Clarification: I'm trying to make an array (or, after all the comments and answers so far, an object type like struct or union) able to hold objects of different data types, including variables, functions, structs, etc. The data types are assumed to be known. I simply want to store different data types and use them in 1 object, like an array.

ChocolateOverflow
  • 460
  • 1
  • 4
  • 11
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/194930/discussion-on-question-by-john-zhau-failure-to-use-pointer-array-in-c). – Samuel Liew Jun 14 '19 at 08:47

4 Answers4

2

This is what you need to do:

#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 is an array of 5 pointers to void (or anything). While printing the elements, you have to cast them to the types that they actually are. For example, arr[3] is a pointer to an array (since you are taking the address of d). Since, the address of the first element is same as the start of the array, we can cast it to a pointer to a char before printing.

For the function (note that just using fun will give you the address of the function), I have assigned the address to f which is a pointer to a function accepting an unspecified arg list and returning void. Then you can invoke f().

That's the gist. Read a good book for more information.

babon
  • 3,615
  • 2
  • 20
  • 20
  • What do ```(int *)```, ```(float *)```, ```(char *)```, and ```(char **)``` do here exactly? Also, why use ```char *d``` instead of ```char d[]```? – ChocolateOverflow Jun 13 '19 at 07:04
  • `arr[4] = fun;` is not allowed in Standard C . Allowing conversion between `void *` values and function pointers (either direction) is a common but non-standard extension. – M.M Jun 13 '19 at 07:10
  • @M.M are you saying I should use a cast like this: `arr[4] = (void *) fun;`? – babon Jun 13 '19 at 07:12
  • @babon I'm saying the code might be rejected no matter what you do, but the reader should be aware that, if it is accepted by the compiler, it is non-standard behaviour that might not work on other compilers – M.M Jun 13 '19 at 07:14
  • @M.M Then what is the *right* way to assign a function to a pointer to a void? Or are you saying there is no *right* way to do this? – babon Jun 13 '19 at 07:16
  • @JohnZhau They are casts. I have updated the program to use `char d[]`. Note how I am printing the c-string. – babon Jun 13 '19 at 07:44
  • @JohnZhau As there is no prototype for `printf` which would define which type of parameters are expected, it is the job of the caller to ensure that proper types of patemeters are passed matching the format specifier in the format string. This is done by these casts. – Gerhardh Jun 13 '19 at 09:26
1

This could be a possible use-case for a union, which would allow you to store pointers to different types:

#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;
}

You still need to keep track of which element contains what actual type, but at least the casting is not necessary, the type is actually guaranteed to be able to hold anything you want to put in it, and the fields help keep track of what you're doing.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
  • This is almost an answer to the problem I described in my comment. It lacks to solve the problem of knowing the type in a function which only gets the array index. I think OP needs to clarify whether I am guessing the actual problem correctly. – Yunnosch Jun 13 '19 at 07:17
  • Good explanation at the end. That is the problem I am referring to. Still needs clarification by OP. – Yunnosch Jun 13 '19 at 07:29
0

You can change int *arr[] to void *arr[], It will work at the time of assignment level, but when you are printing you cannot cast void to int, it will throw error.

Raja Sharma
  • 460
  • 1
  • 7
  • 19
-1

You cannot assign an integer pointer to the address of a variable which is other than an integer data type.

You can change the datatype of all the variables to integer datatype or use a generic pointer for working.

Saurav Rai
  • 2,171
  • 1
  • 15
  • 29
  • *"You cannot assign an integer pointer to the address of a variable which is other than an integer data type. "* - Yes, you can. – klutt Jun 13 '19 at 06:59
  • @ John Zhau By generic pointer, I mean void pointer. [link text](https://www.geeksforgeeks.org/void-pointer-c-cpp/) – Saurav Rai Jun 13 '19 at 07:58