0

I want to pass a void pointer array to a function which fills it with the result it works fine with integer but I have troubles returning char*

int function(void *arr[]);
int main(void) {
 void *arr[3];
 function(arr);
 printf("%d\n", *(int *)&arr[0]);
 printf("%d\n", *(int *)&arr[1]);
 printf("%s\n", (char *)&arr[2]);
}
int function(void *arr[]){
 arr[0] = (void*)(int)4;
 arr[1] = (void*)(int)6;
 char* test = "abc";
 arr[2] = (void*)test;
 return 0;
}

for the String I don't get the right value

asked Dec 30, 2020 at 10:53
13
  • "I want to pass a void pointer array to a function which fills it with the result" - why?! Commented Dec 30, 2020 at 10:54
  • integer isn't a type, and sizeof(int) is not necessarily sizeof(void*). Commented Dec 30, 2020 at 10:55
  • @Dai this is just a example, I want to pass a sql string to a function and the sql defines how many result values I get. Commented Dec 30, 2020 at 10:57
  • What on earth does SQL have to do with abusing void*? Commented Dec 30, 2020 at 10:59
  • 1
    You are coding in a language with undefined behavior. "Works" has actually little to do with correctness of the code. You may just (int)arr[0] and it will also "work" and also be correct. Commented Dec 30, 2020 at 11:24

3 Answers 3

2

arr has type void(*)[3].

arr[0] has type void*. The fact that it stores a suitably converted value of 4 is irrelevant.

&arr[0] has type void**.

(int *)&arr[0] has type int*, but it points to an object of type void* instead of pointing to an object of type int. This is not what pointers normally do. You can have such a pointer, but the only thing you can legally do with it is convert it back to the right type, in this case void**. You are not doing that.

*(int *)&arr[0] has type int.

Here you are accessing an object of type void* through an lvalue of type int. This is undefined behaviour. Don't do that.

If you want to convert arr[0] back to int, just do that:

printf("%d\n", (int)arr[0]);

Likewise, if you want to convert arr[2] back to char*, do just that:

printf("%s\n", (char*)arr[2]);
answered Dec 30, 2020 at 11:39
Sign up to request clarification or add additional context in comments.

Comments

1

You may pass an array of voids, and assign that array elements to a dynamically allocated memory region that stores the pointed-to value.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int function(void *arr[]){ 
 arr[0] = malloc(sizeof(int));
 if (arr[0] == NULL) goto ERR_MALLOC_0;
 *(int*)arr[0] = 4;
 arr[1] = malloc(sizeof(int));
 if (arr[1] == NULL) goto ERR_MALLOC_1;
 *(int*)arr[1] = 6;
 const char *const test = "abc";
 arr[2] = malloc(strlen(test));
 if (arr[2] == NULL) goto ERR_MALLOC_2;
 strcpy(arr[2], test);
 return 0;
 // remember about error checking
 free(arr[2]);
 ERR_MALLOC_2:
 free(arr[1]);
 ERR_MALLOC_1:
 free(arr[0]);
 ERR_MALLOC_0:
 return -1;
}
int main(void) {
 void *arr[3];
 int err = function(arr);
 if (err == -1) abort();
 // & is the address of element, not it's element
 printf("%d\n", *(int*)arr[0]);
 printf("%d\n", *(int*)arr[1]);
 printf("%s\n", (char*)arr[2]);
 // remember to free memory
 for (int i = 0; i < 3; ++i) {
 // funny how we do not need to know the effective type
 free(arr[i]);
 }
}

But such function is just plainly confusing and will result in many, many bugs and problems. Instead just actually use variables of proper type:

#include <stdlib.h>
#include <string.h>
int function(int *val1, int *val2, char **string) {
 *val1 = 3;
 *val2 = 6;
 const char *test = "abc";
 *string = malloc(strlen(test));
 if (*string == NULL) return -1;
 strcpy(*string, test);
 return 0;
}
int main(void) {
 int val1; 
 int val2;
 char *string;
 int err = function(&val1, &val2, &string);
 if (err == -1) abort();
 printf("%d\n", val1);
 printf("%d\n", val2);
 printf("%s\n", string);
 free(string);
}

If you are really striving for implementing some virtual representation and operations on different data types, using plain "array of void pointers" will get you nowhere, because such array doesn't know what is the underlying type of the value that is being stored - you, as a programmer, have to know what is inside that array (ie. that arr[0] is an int and arr[2] is a char*), so as you know it you might as well just use variables of proper types from the start.

answered Dec 30, 2020 at 11:34

3 Comments

"so as you know it you might as well just use variables of proper types from the start." - and when you don't you need to use a tagged-union type.
Thank you! maybe I go with array of int* and array of char* because those are the only types I need. But the number of results for each type is not defined.
and when you don't you need to use a tagged-union type as would an intermediate programmer do, which results in what I call big fat switched, which are hard to maintain, reason about and very hard to refactor. A way better design that will last for years is creating an interface with proper dispatch table. Anyway, design always depends.
1
arr[0] = (void*)(int)4;

The above line cast the integer 4 as void pointer (address) and stores it in the array arr as pointer address. I guess that's not what you wanted.

In order to access data using a void pointer the way you want, first make it point to a valid memory address, which will hold the data when the function exits. You have to be careful while assigning memory address to a void pointer inside a function, all variables in that function's stack (local variables) will be popped off the from the stack when the function exits, making that memory addresses invalid. Only use static (or global) or dynamic memory while assigning the memory address to your pointer inside the function, if you want to use it outside the function.

answered Dec 30, 2020 at 11:47

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.