Reputation: 2255
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
Upvotes: 0
Views: 1355
Reputation: 827
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.
Upvotes: 1
Reputation: 119847
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]);
Upvotes: 2
Reputation: 140960
You may pass an array of void
s, 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.
Upvotes: 1