I have this working code:
#import <stdlib.h>
#import <stdio.h>
typedef struct myarray {
int len;
void* items[];
} MYARRAY;
MYARRAY *collection;
void
mypop(void** val) {
puts(collection->items[collection->len]);
*val = collection->items[collection->len--];
}
void
mypush(void* val) {
int len = collection->len++;
collection->items[len] = val;
puts(collection->items[len]);
}
int
main() {
puts("Start");
collection = malloc( sizeof *collection + (sizeof collection->items[0] * 1000) );
collection->len = 0;
puts("Defined collection");
mypush("foo");
puts("Pushed foo");
mypush("bar");
puts("Pushed bar");
char str1;
mypop((void*)&str1);
puts("Popped bar");
puts(&str1);
char str2;
mypop((void*)&str2);
puts("Popped foo");
puts(&str2);
puts("Done");
return 0;
}
It outputs:
Start
Defined collection
foo
Pushed foo
bar
Pushed bar
(null)
Popped bar
bar
Popped foo
�ߍ
Done
It should output this instead:
Start
Defined collection
foo
Pushed foo
bar
Pushed bar
bar
Popped bar
bar
foo
Popped foo
foo
Done
Being new to C I am not really sure what's going on or why the output is "corrupted" like that. It seems though that the double pointer void**
allows you to pass in a pointer and get out a value without knowing the type, so yay. But wondering if one could show how this code should be implemented so I can get a feel for how to do such a thing.
Compiled with clang:
clang -o example example.c
Update
I've updated my code to reflect the latest answers, but still not sure the malloc of the collection is correct.
#include <stdlib.h>
#include <stdio.h>
typedef struct myarray {
int len;
void* items[];
} MYARRAY;
MYARRAY *collection;
void
mypop(void** val) {
--collection->len;
puts(collection->items[collection->len]);
*val = collection->items[collection->len];
}
void
mypush(void* val) {
int len = collection->len++;
collection->items[len] = val;
puts(collection->items[len]);
}
int
main() {
puts("Start");
collection = malloc( sizeof *collection + (sizeof collection->items[0] * 1000) );
collection->len = 0;
puts("Defined collection");
mypush("foo");
puts("Pushed foo");
mypush("bar");
puts("Pushed bar");
char *str1;
mypop((void**)&str1);
puts("Popped bar");
puts(str1);
char *str2;
mypop((void**)&str2);
puts("Popped foo");
puts(str2);
free(collection);
puts("Done");
return 0;
}
*value
- No. You cannot dereference avoid
pointer. You must cast to a valid type first. You are free to usevoid
just as any other pointer, except you cannot dereference it (it has no type). – FalcongentleC
like herevoid* items[];
? I guess not. – Electronicvoid *
is the "homogeneous" type of collection in C, it's not. You should use not usevoid *
this way. It's a bad practice. – Wardrobefree(void*)
uses it, and several other core lib functions. Explaining why it's bad practice would be helpful too. – Betelvoid *
lose the information of the type,free()
take avoid *
because it doesn't care about the type,malloc()
return avoid *
because it doesn't know the type. Also, what you trying to do is never used in any production code in C. With your structure, If I want stock aint
I would need to allocate each int withmalloc()
. This would be a performance killer. Your code is ok for a string but not for any scalar. In C, you can code a generic linked list with some trick, but you can't code a generic vector container.void *
=>char *
or find a macro solution. – Wardrobe