plain C have nice feature - void type pointers, which can be used as pointer to any data type.
But, assume I have following struct:
struct token {
int type;
void *value;
};
where value field may point to char array, or to int, or something else.
So when allocating new instance of this struct, I need:
1) allocate memory for this struct;
2) allocate memory for value and assign it to value field.
My question is - is there ways to declare "array of type void", which can be casted to any another type like void pointer?
All I want is to use "flexible member array" (described in 6.7.2.1 of C99 standard) with ability to casting to any type.
Something like this:
struct token {
int type;
void value[];
};
struct token *p = malloc(sizeof(struct token) + value_size);
memcpy(p->value, val, value_size);
...
char *ptr = token->value;
I suppose declaring token->value as char or int array and casting to needed type later will do this work, but can be very confusing for someone who will read this code later.
Well, sort of, but it's probably not something you want:
struct token {
// your fields
size_t item_size;
size_t length
};
struct token *make_token(/* your arguments */, size_t item_size, size_t length)
{
struct token *t = malloc(sizeof *t + item_size * length);
if(t == NULL) return NULL;
t->item_size = item_size;
t->length = length;
// rest of initialization
}
The following macro can be used to index your data (assuming x is a struct token *):
#define idx(x, i, t) *(t *)(i < x->length ? sizeof(t) == x->item_size ?
(void *)(((char *)x[1]) + x->item_size * i)
: NULL : NULL)
And, if you like, the following macro can wrap your make_token function to make it a little more intuitive (or more hackish, if you think about it that way):
#define make_token(/* args */, t, l) (make_token)(/* args */, sizeof(t), l)
Usage:
struct token *p = make_token(/* args */, int, 5); // allocates space for 5 ints
...
idx(p, 2, int) = 10;
Expanding on AShelly's answer you can do this;
/** A buffer structure containing count entries of the given size. */
typedef struct {
size_t size;
int count;
void *buf;
} buffer_t;
/** Allocate a new buffer_t with "count" entries of "size" size. */
buffer_t *buffer_new(size_t size, int count)
{
buffer_t *p = malloc(offsetof(buffer_t, buf) + count*size);
if (p) {
p->size = size;
p->count = count;
}
return p;
}
Note the use of "offsetof()" instead of "sizeof()" when allocating the memory to avoid wasting the "void *buf;" field size. The type of "buf" doesn't matter much, but using "void *" means it will align the "buf" field in the struct optimally for a pointer, adding padding before it if required. This usually gives better memory alignment for the entries, particularly if they are at least as big as a pointer.
Accessing the entries in the buffer looks like this;
/** Get a pointer to the i'th entry. */
void *buffer_get(buffer_t *t, int i)
{
return &t->buf + i * t->size;
}
Note the extra address-of operator to get the address of the "buf" field as the starting point for the allocated entry memory.
I would probably do this:
struct token {
int type;
void *value;
};
struct token p;
p.value = malloc(value_size);
p.value[0] = something;
p.value[1] = something;
...
edit, actually you have to typecast those p.value[index] = somethings. And/or use a union to not have to typecast.
You can't have an array of 'void' items, but you should be able to do something like what you want, as long as you know value_size when you do the malloc. But it won't be pretty.
struct token {
int type;
void *value;
};
value_size = sizeof(type)*item_count;
struct token *p = malloc(sizeof(struct token) + value_size);
//can't do memcpy: memcpy(p->value, val, value_size);
//do this instead
type* p = (type*)&(p->value);
type* end = p+item_count;
while (p<end) { *p++ = someItem; }
Note that you need an extra address-of operator when you want to get the extra storage.
type *ptr = (type*)&(token->value);
This will 'waste' sizeof(void*) bytes, and the original type of value doesn't really matter, so you may as well use a smaller item. I'd probably typedef char placeholder; and make value that type.
following structure can help you.
struct clib_object_t {
void* raw_data;
size_t size;
};
struct clib_object_t*
new_clib_object(void *inObject, size_t obj_size) {
struct clib_object_t* tmp = (struct clib_object_t*)malloc(sizeof(struct clib_object_t));
if ( ! tmp )
return (struct clib_object_t*)0;
tmp->size = obj_size;
tmp->raw_data = (void*)malloc(obj_size);
if ( !tmp->raw_data ) {
free ( tmp );
return (struct clib_object_t*)0;
}
memcpy ( tmp->raw_data, inObject, obj_size);
return tmp;
}
clib_error
get_raw_clib_object ( struct clib_object_t *inObject, void**elem) {
*elem = (void*)malloc(inObject->size);
if ( ! *elem )
return CLIB_ELEMENT_RETURN_ERROR;
memcpy ( *elem, inObject->raw_data, inObject->size );
return CLIB_ERROR_SUCCESS;
}
More Details : clibutils
Array of type void is not supporting in c/c++.
Example like:
int main() {
void alexa[]; // error: declaration of ‘alexa’ as array of void
return 0;
}
Array of void pointer is supported in c/c++.
Example below:
int main(int argc, char argv*[])
{
void *alexa[100]; // Compiled successfully
return 0;
}
Related
typedef struct {
void *end;
void *start;
int size;
int arrs [];
} st;
void *doStuff(void *starter, void *ender) {
st *s = (st *) malloc(sizeof(st));
s->end = ender;
s->start = starter;
int sayz = 1;
s->size = (int) (ender - starter);
int a [s->size];
memset(a, 0, sizeof a);
s->arrs = a; // This line gives error
return s;
}
the line "st->arrs = a;" gives me the "Invalid use of flexible array member" error. Does anybody know how I can save an array inside a structure? The language is C
This is what you want, assuming starter and ender point to char objects. I've also cleaned up your indenting and formatting.
typedef struct {
void *end;
void *start;
ptrdiff_t size; // Note that a diff of pointers should be a ptrdiff_t
int arrs[];
} st;
st *doStuff(void *starter, void *ender) {
ptrdiff_t size = (char*)ender - (char*)starter; // Calculate size first so it's available to use in malloc
st *s = malloc(size + sizeof st);
s->end = ender;
s->start = starter;
s->size = size;
memset(s->arrs, 0, size * sizeof s->arrs[0]); // since array is allocated, no need to create a redundant array
return s;
}
A flexible array member is not a pointer; you do not assign an address or an array to it. You allocate space for it as part of the space you allocate for the structure, and then you use it like an array. Change st *s = (st *) malloc(sizeof(st)); to st *s = malloc(sizeof *s + N * sizeof *s->arrs);, where N is the number of elements you want for the array.
Then you can initialize the array to zero with memset(s->arrs, 0, N * sizeof *s->arrs);.
Note that ender - starter is not proper C code. The type of ender and starter is void *, and the C standard does not define the behavior of subtracting pointers to void. GCC does, but this gives you a number of bytes, not, in general, a number of array elements. To subtract ender and starter properly, use (T *) ender - (T *) starter, where T is the type of object they point to.
I'm pretty bad at remembering C rules with structs. Basically, I have a struct like this:
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
Where the char* ptr will only be one character max.
In my program, I have to allocate and free memory to a fake disk (declared globally as char disk[100];) using my own functions:
char disk[100];
void disk_init() {
for(int i = 0; i < 100; ++i) {
disk[i] = memory[i] = 0;
}
}
struct Xalloc_struct* Xalloc(int size) {
// error checking
// ...
// run an algorithm to get a char* ptr back to a part of the global disk
// array, where index i is the index where content at disk[i] starts
char* ptr = &disk[i];
struct Xalloc_struct *ret = malloc(sizeof(struct Xalloc_struct));
ret->size = size;
ret->ptr = malloc(sizeof(char));
ret->ptr = ptr;
return ret;
}
int Xfree(void* ptr) {
struct Xalloc_struct* p = (struct Xalloc_struct*) ptr;
int size = p->size;
int index = *(p->ptr);
// .. more stuff here that uses the index of where p->ptr points to
free(p->ptr);
free(p);
return 0;
}
int main() {
disk_init();
struct Xalloc_struct* x = Xalloc(5);
Xfree(x);
return 0;
}
When this compiles I get quite a few errors:
error: invalid application of ‘sizeof’ to incomplete type ‘struct Xalloc_struct’
struct Xalloc_struct *ret = malloc(sizeof(struct Xalloc_struct));
^
error: dereferencing pointer to incomplete type
ret->size = size;
^
error: dereferencing pointer to incomplete type
free(x->ptr);
^
error: dereferencing pointer to incomplete type
int size = cast_ptr->size;
^
error: dereferencing pointer to incomplete type
int free_ptr = *(cast_ptr->ptr);
^
So, how should I be allocating and deallocating these structs? And how can I modify / edit what they contain?
First problem is Xalloc_struct is a type, not the name of a struct. You declared that type with this:
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
typedef is of the form typedef <type name or struct definition> <name of the type>. So you declared the type Xalloc_struct to be struct { char *ptr; int size; }.
That means you use it like any other type name: Xalloc_struct somevar = ...;.
Had you declared the struct with a name...
struct Xalloc_struct {
char* ptr;
int size;
};
Then it would be struct Xalloc_struct somevar = ...; as you have.
The rule of thumb when allocating memory for an array (and a char * is an array of characters) is you allocate sizeof(type) * number_of_items. Character arrays are terminated with a null byte, so for them you need one more character.
Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->ptr = malloc(sizeof(char) * num_characters+1);
But if you're only storing one character, there's no need for an array of characters. Just store one character.
typedef struct {
char letter;
int size;
} Xalloc_struct;
Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->letter = 'q'; /* or whatever */
But what I think you're really doing is storing a pointer to a spot in the disk array. In that case, you don't malloc at all. You just store the pointer like any other pointer.
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->ptr = &disk[i];
Then you can read that character with ret->ptr[0].
Since you didn't allocate ret->ptr do not free it! That will cause a crash because disk is in stack memory and cannot be free'd. If it were in heap memory (ie. malloc) it would probably also crash because it would try to free in the middle of an allocated block.
void Xalloc_destroy(Xalloc_struct *xa) {
free(xa);
}
Here's how I'd do it.
#include <stdio.h>
#include <stdlib.h>
char disk[100] = {0};
typedef struct {
char *ptr;
int idx;
} Disk_Handle_T;
static Disk_Handle_T* Disk_Handle_New(char *disk, int idx) {
Disk_Handle_T *dh = malloc(sizeof(Disk_Handle_T));
dh->idx = idx;
dh->ptr = &disk[idx];
return dh;
}
static void Disk_Handle_Destroy( Disk_Handle_T *dh ) {
free(dh);
}
int main() {
Disk_Handle_T *dh = Disk_Handle_New(disk, 1);
printf("%c\n", dh->ptr[0]); /* null */
disk[1] = 'c';
printf("%c\n", dh->ptr[0]); /* c */
Disk_Handle_Destroy(dh);
}
What you are attempting to accomplish is a bit bewildering, but from a syntax standpoint, your primary problems are treating a typedef as if it were a formal struct declaration, not providing index information to your Xalloc function, and allocating ret->ptr where you already have a pointer and storage in disk.
First, an aside, when you are specifying a pointer, the dereference operator '*' goes with the variable, not with the type. e.g.
Xalloc_struct *Xalloc (...)
not
Xalloc_struct* Xalloc (...)
Why? To avoid the improper appearance of declaring something with a pointer type, (where there is no pointer type just type) e.g.:
int* a, b, c;
b and c above are most certainly NOT pointer types, but by attaching the '*' to the type it appears as if you are trying to declare variables of int* (which is incorrect).
int *a, b, c;
makes it much more clear you intend to declare a pointer to type int in a and two integers b and c.
Next, in Xfree, you can, but generally do not want to, assign a pointer type as an int (storage size issues, etc.) (e.g. int index = *(p->ptr);) If you need a reference to a pointer, use a pointer. If you want the address of the pointer itself, make sure you are using a type large enough for the pointer size on your hardware.
Why are you allocating storage for ret->ptr = malloc(sizeof(char));? You already have storage in char disk[100]; You get no benefit from the allocation. Just assign the address of the element in disk to ptr (a pointer can hold a pointer without further allocation) You only need to allocate storage for ret->ptr if you intend to use the memory you allocate, such as copying a string or multiple character to the block of memory allocated to ret->ptr. ret->ptr can store the address of an element in data without further allocation. (it's unclear exactly what you intend here)
You are free to use a typedef, in fact it is good practice, but when you specify a typedef as you have, it is not equivalent to, and cannot be used, as a named struct. That is where your incomplete type issue arises.
All in all, it looks like you were trying to do something similar to the following:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
char disk[100] = "";
Xalloc_struct *Xalloc (int size, int i) {
char *ptr = &disk[i];
Xalloc_struct *ret = malloc (sizeof *ret);
ret->size = size;
// ret->ptr = malloc (sizeof *(ret->ptr)); /* you have a pointer */
ret->ptr = ptr;
return ret;
}
int Xfree (void *ptr) {
Xalloc_struct *p = (Xalloc_struct *) ptr;
// int size = p->size; /* unused */
// int index = *(p->ptr); /* what is this ?? */
// .. more stuff here that uses the index of where p->ptr points to
// free (p->ptr);
free (p);
return 0;
}
int main (void) {
int i = 0;
Xalloc_struct *x = Xalloc (5, i++);
Xfree(x);
return 0;
}
Look at the difference in how the typedef is used and let me know if you have any questions.
You can't have arrays of structures with flexible array members.
This is the TL;DR of this question. And thinking about it, it makes perfect sense.
However, may one simulate an array of structures with flexible array member - let's call them swfam - of fixed size as below :
#include <assert.h>
#include <stdlib.h>
typedef struct {
int foo;
float bar[];
} swfam_t; // struct with FAM
typedef struct { // this one also has a FAM but we could have used a char array instead
size_t size, // element count in substruct
count; // element count in this struct
char data[];
} swfam_array_t;
#define sizeof_swfam(size) (sizeof(swfam_t) + (size_t)(size) * sizeof(float))
swfam_array_t *swfam_array_alloc(size_t size, size_t count) {
swfam_array_t *a = malloc(sizeof(swfam_array_t) + count * sizeof_swfam(size));
if (a) {
a->size = size;
a->count = count;
}
return a;
}
size_t swfam_array_index(swfam_array_t *a, size_t index) {
assert(index < a->count && "index out of bounds");
return index * sizeof_swfam(a->size);
}
swfam_t *swfam_array_at(swfam_array_t *a, size_t index) {
return (swfam_t *)&a->data[swfam_array_index(a, index)];
}
int main(int argc, char *argv[]) {
swfam_array_t *a = swfam_array_alloc(100, 1000);
assert(a && "allocation failed");
swfam_t *s = swfam_array_at(a, 42);
s->foo = -18; // do random stuff..
for (int i = 0; i < 1000; ++i)
s->bar[i] = (i * 3.141592f) / s->foo;
free(a);
return 0;
}
Is the trick valid C99 / C11 ? Am I lurking towards undefined behaviour ?
One way to do this would be to use a pointer member instead of a flexible array. You would then have to manually allocate its size via malloc() et. al. [] is typically used only when the array is initialized on declaration, which is not possible with struct, which is essentially a definition, not a declaration. The ability to immediately declare an instance of the struct type does not change the nature of the definition, it's just for convenience.
typedef struct {
int foo;
float* bar; } swfam_t; // struct with FAM
As the title says i want to pass structure to function and allocate memory, maybe it's a stupid question but i can't find the answer..
structName *allocate_memory( int *numPlayers,structName )
{
structName *retVal = malloc( sizeof(struct structName) * (*numPlayers) );
return retVal;
}
The problem is in parameters structName what should go there?
if you need the full code i can post it but i think there is no need..
You can't pass in a type as a parameter. But you can pass in its size:
void *allocate_memory( int *numPlayers, size_t struct_size)
{
void *retVal = malloc( struct_size * (*numPlayers) );
if (!retVal) {
perror("malloc failed!");
exit(1);
}
return retVal;
}
Then call it like this:
struct mystruct *s = allocate_memory(&numPlayers, sizeof(struct mystruct));
Or you just do this instead, assuming you want the memory initialized to all 0:
struct mystruct *s = calloc(numPlayers, sizeof(struct mystruct));
You can use a void pointer there, void can take anything...hope it helps....
You have two options, the first returning a new pointer (see allocate_memory) and the second is to fill in an existing pointer (see allocate_memory2. In both cases I converted numPlayers to int because it isn't necessary to provide by reference
struct structName *allocate_memory(int numPlayers)
{
struct structName *retVal = malloc(sizeof(struct structName) * numPlayers);
return retVal;
}
void allocate_memory2(struct structName **target, int numPlayers)
{
*target = malloc(sizeof(struct structName) * numPlayers);
}
int main(int argc, char** argv)
{
struct structName *str;
struct structName *str2;
//After this line str is a valid pointer of size 20*sizeof(struct structName)
str = allocate_memory(20);
//After this line str2 is a valid pointer of size 20*sizeof(struct structName)
allocate_memory2(&str2, 20);
}
You cannot pass a type as a parameter to a function.
You basically have two options realizing your allocate_memory function:
Instead of passing the name of the type simply pass the size of the type:
void *allocate_memory( int *numPlayers, size_t size). But this is only a trivial wrapper for malloc.
You could write a macro #define allocate_memory(num, type) (malloc(num * sizeof(type))) to do the job.
Maybe you're looking for a combination of both if you want to track some statistics of the memory allocated or do additional checks:
#define allocate_memory(num, type) (my_malloc((num), sizeof((type))))
void *my_malloc(int num, size_t size)
{
void *pMem = malloc(num * size);
if (pMem == NULL)
{
/* do error handling */
}
return (pMem);
}
You can use the above macro as follows:
pInt = allocate_memory(5, int); // allocates 5 integers
pStruct = allocate_memory(10, some_struct); // allocates 10 some_structs
I'm pretty rust at my C still and I am just not figuring this out. What I am trying to do is to implement my own malloc so I can keep track of allocations and debug missing calls to free(). I have a header like this:
typedef struct MemoryInfo {
mem_Kind kind;
unsigned int id;
struct MemoryInfo* prev;
struct MemoryInfo* next;
} MemoryInfo;
And my custom malloc looks something like this:
void* my_malloc(mem_Kind kind, unsigned int size) {
MemoryInfo* mem;
allocCount++;
mem = (MemoryInfo*)malloc(sizeof(MemoryInfo) + size);
mem->id = id;
mem->kind = kind;
// set prev/next...
return mem + sizeof(MemoryInfo); // return pointer to memory after header
}
But I'm clearly getting my pointer arithmetic wrong because it blows up pretty horribly very quickly. However if I add a void* memory to the end of my struct and do another malloc then it seems to do fine, the problem with that is that I can't really find the header in my_free if I do that. I'm trying to basically prepend the header so I can do some reverse pointer arithmetic to get the header in free.
void my_free(void* memory) {
MemoryInfo* mem = memory - sizeof(MemoryInfo); // not correct either
allocCount--;
free(mem);
}
What am I doing wrong here?
I think you have a problem with adding to pointer. It has to be like this:
return (char*)mem + sizeof(MemoryInfo); // return pointer to memory after header
and
void my_free(void* memory) {
MemoryInfo* mem = (MemoryInfo*)((char*)memory - sizeof(MemoryInfo)); // not correct either
allocCount--;
free(mem);
}
By the way. Look at this program.
#include <stdio.h>
typedef struct MemoryInfo {
int kind;
unsigned int id;
struct MemoryInfo* prev;
struct MemoryInfo* next;
} MemoryInfo;
int main()
{
MemoryInfo* ptr = 0;
printf("sizeof: %d\n",sizeof(MemoryInfo));
printf("%d\n",ptr+3);
return 0;
}
I have added 3 to pointer to MemoryInfo, but its value become 3*sizeof(MemoryInfo).
Your pointer arithmetic is wrong. in ptr+1 the +1 already uses the correct increment (sizeof *ptr). You would have to increment by sizeof *ptr if ptr were a char pointer, but it is not.
void *my_malloc(mem_Kind kind, unsigned int size) {
MemoryInfo mem;
allocCount++;
mem = malloc(sizeof *mem + size);
mem->id = id;
mem->kind = kind;
// set prev/next...
return mem + 1; // return pointer to memory after header
}
void my_free(void *memory) {
MemoryInfo *mem = memory; // not correct either
mem -= 1;
allocCount--;
free(mem);
}
Also, please take into consideration that malloc() and friends should return a pointer that is suitable to every object, and has to be aligned to the natural boundary for any object. (this could be 32 bits, 64 bits, or anything that your platform dictates)
Your sizes could fail for sizeof (int)==2 and sizeof (void*) == 8 , for instance. (but which seems a very rare case, luckily)
good practice is define like this:
struct some_struct {
size_t data_size;
struct some_struct *next, *prev;
void * struct_data[];
}
and us it like that:
struct some_struct *get_some_struct ( void *buf,size_t buflen,struct some_struct **next){
*next=0;
struct some_struct *s=(struct some_struct *)buf;
if ( s && buflen < sizof(*s) + s->data_size )
*next = (char*)s + s->data_size;
return s;
else
return 0;
}
So, if you need to iterate through structures, you can get properly the offset of next structure in buffer. I just want you to get the approach.
Will be pleased if you'll get it