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.

1
  • Comments are not for extended discussion; this conversation has been moved to chat. Commented Jun 14, 2019 at 8:47

4 Answers 4

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.

Sign up to request clarification or add additional context in comments.

7 Comments

What do (int *), (float *), (char *), and (char **) do here exactly? Also, why use char *d instead of char d[]?
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 are you saying I should use a cast like this: arr[4] = (void *) fun;?
@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 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?
|
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.

2 Comments

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.
Good explanation at the end. That is the problem I am referring to. Still needs clarification by OP.
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.

1 Comment

I've also tried using void *arr[] but I'm given warning: dereferencing ‘void *’ pointer
-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.

2 Comments

"You cannot assign an integer pointer to the address of a variable which is other than an integer data type. " - Yes, you can.
@ John Zhau By generic pointer, I mean void pointer. link text

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.