How to pass structure to function to allocate memory - c

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

Related

Malloc within function not changing pointer value

So when I pass a data type like a struct to assign some memory to it I find that the pointer doesn't change within the main scope. This further becomes a problem when I try to free the memory but obviously if its using the original pointer it will be pointing at the stack address.
void allocate(int *value){
value = malloc(10 * sizeof(int));
}
int main(){
int val2;
allocate(&val2);
free(&val2);
return 0;
}
I can fix this by using a double pointer to be passed into the allocate function but some course work I'm doing requires to only pass a pointer and I cant get it to update the pointer when it returns to main. I have looked around for a while but cant find a straight forward answer, I feel like my coursework is wrong but that might be my lack of understanding.
The requirement to "only pass a pointer" seems contrived, and you could argue that a pointer to pointer (not a "double pointer") is a pointer, but perhaps you could use void * to punch a hole in the type system. Or use a struct:
#include <stdlib.h>
#include <stdio.h>
struct intbuffer {
int *d;
size_t cap;
};
void *
xmalloc(size_t s)
{
void *r = malloc(s);
if( r == NULL ){
perror("malloc");
exit(1);
}
return r;
}
void
allocate(void *p, size_t s)
{
*(int **)p = xmalloc(s * sizeof(int));
}
void
allocate2(struct intbuffer *p)
{
p->d = xmalloc(p->cap * sizeof *p->d);
}
int
main(void)
{
int *val2;
struct intbuffer v;
allocate(&val2, 10);
free(val2);
v.cap = 10; /* Horrible api!! */
allocate2(&v);
free(v.d);
return 0;
}
Note that setting the capacity in the struct prior to making the call to allocate is a violation of many principles of software design, but this whole thing is absurdly contrived due to the bizarre artificial limitations.
There are not enough *'s in each place, but you will have to figure out what that means.
void allocate(int** value){
*value = malloc(10 * sizeof(int));
}
int main(){
int* val2;
allocate(&val2);
free(val2);
return 0;
}

Creating, returning, and casting a struct with a char pointer in C

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.

Storing the length of a dynamic array of struct

Can anyone help me with this? Say I have the following struct:
typedef struct mystruct{
int data1;
int data2;
}mystruct;
And I created an array of struct using the below code:
main(void) {
mystruct **new_mystruct = function();
... need to know the length of new_mystruct here ...
}
mystruct **function(){
... code to determine length of array here ...
mystruct **new_mystruct= malloc(length_of_array * sizeof(mystruct));
... code to fill array here ...
return new_mystruct;
}
What is the best way to return the length of my array, assuming length_of_array is dynamically generated during the run time of my function?
I hope I'm making sense. Thank you in advance.
You could pass the length as a reference to the function, and have the function fill it in:
mystruct *function(size_t *size)
{
/* ... */
mystruct *new_mystruct = malloc(length_of_array * sizeof(mystruct))
*size = length_of_array;
/* ... */
return new_mystruct;
}
int main(void)
{
/* ... */
size_t size;
mystruct *new_mystruct = function(&size);
/* ... */
}
Make wrapper struct:
typedef struct_array_
{
mystruct * p;
size_t size;
} struct_array;
Your creation function can return this by value:
struct_array create_array(size_t n)
{
mystruct * p = malloc(n * sizeof *p);
struct_array result = { p, n };
return result;
}
You should make a matching clean-up function:
void destroy_array(struct_array a)
{
free(a.p);
}
You can also make a copy_array function that uses memcpy to create a copy.
size_t function(MyStruct *mystruct)
{
/*...*/
mystruct = malloc(length_of_array * sizeof(MyStruct));
/*...*/
return length_of_array;
}
and use
MyArray *new_array;
size_t lenght;
lenght = function(new_array);
You can either return a struct (or pointer to struct) that contains both the length and the pointer to the allocated array, or you can pass in a pointer to a variable to received the length.
int length;
mystruct **new_mystruct = function(&length);
I prefer the stuct approach.

Passing pointers for memory allocation inside a function?

I need to allocate arrays of structures in a bunch of different places in my program, thus putting the work inside a function (VS 2010). Compiler gives warning about uninitialized variable used. So how do I pass it, and how to declare it in the function. I've tried many variations of "&" and "*", to no avail.
(I apologize in advance if my code causes any form of nausea...I'm an English major.)
struct s_stream {
int blah;
};
void xxyz(void)
{
struct s_stream **StreamBuild;
char *memBlock_1;
xalloc(StreamBuild, memBlock_1, 20);
}
void xalloc(struct s_stream **StreamStruct, char *memBlock, int structCount)
{
int i = sizeof(struct s_stream *);
if ((StreamStruct=(struct s_stream **) malloc(structCount * i)) == NULL)
fatal("failed struct pointer alloc");
int blockSize = structCount * sizeof(struct s_stream);
if ((memBlock = (char *) malloc(blockSize)) == NULL)
fatal("failed struct memBlock alloc");
// initialize all structure elements to 0 (including booleans)
memset(memBlock, 0, blockSize);
for (int i = 0; i < structCount; ++i)
StreamStruct[i]=(struct s_stream *) &memBlock[i*sizeof(struct s_stream) ];
}
I'm not exactly sure I understand your question, but it seems like you want a function that will create a dynamically allocated array of struct s_stream objects and return them to the caller. If that's the case, it's pretty easy:
void easiest(void)
{
struct s_stream *array = malloc(20 * sizeof(struct s_stream));
}
You could move the malloc() off into its own function and return the pointer:
void caller(void)
{
struct s_stream *array = create_array(20);
}
struct s_stream *create_array(int count)
{
return malloc(count * sizeof(struct s_stream));
}
Or if you insist on passing the array as a parameter:
void caller(void)
{
struct s_stream *array;
create_array(&array, 20);
}
void create_array(struct s_stream **array, int count)
{
*array = malloc(count * sizeof(struct s_stream));
}
You are passing a copy of the pointer memBlock_1 to xalloc, so the address returned by malloc is written to the copy and never reaches the calling function. Since you presumably want the address to be available to xxyz in memBlock_1, you have to pass a pointer-to-pointer-to-char as the second argument,
void xalloc(..., char **memBlock, ...)
and call it with xalloc(..., &memBlock_1, ...);. In the body of xalloc, replace all occurrences of memBlock with *memblock, e.g. (*memblock = malloc(blockSize)) == NULL (no need to cast).
Analogously, the StreamStruct parameter of xalloc never changes the StreamBuild pointer-to-pointer-to-struct s_stream in xxyz. If I interpret your intentions correctly, you would also have to add a pointer layer to that parameter, void xalloc(struct s_stream ***StreamStruct, ..., ...), pass the address of StreamBuild in the call, xalloc(&StreamBuild, ..., ...) and dereference the pointer in the function body, e.g. (*StreamStruct = malloc(structCount * i)) == NULL.
Is there any reason you're not using a regular array? For example;
struct s_stream* streamArray = malloc(sizeof(s_stream*structCount));
Then you have an array of s_stream you can just access with streamArray[0] to streamArray[structCount-1] without dereferencing any extra pointers.

array of type void

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;
}

Resources