array of pointers allocation - c

typedef struct
{
struct table **symbols; // array of the stack
int top; //index of the top element
int size; //maximum size of the stack
}stack;
void *createStack(int size)
{
stack *stck;
stck = (stack *) malloc(sizeof(stack));
stck->symbols = ....
stck->size = size;
stck->top = -1;
printf("stack is created --> size is : %d \n",size);
}
Here I need to allocate my stack's symbol array which is "..." but I couldn't figure out it's syntax, pls help : )

(struct table **)malloc(size * sizeof(struct table*));
But that's if you want to pre-allocate all the space at once. If you want to allocate more as you go, you could start with something smaller than size and allocate more in your push() function when you run out of space.

malloc(size * sizeof(struct table*));

Is symbols intended to be a 1-d array of pointer to struct table or a 2-d array of struct table?
stck->symbols = malloc(sizeof *(stck->symbols) * numberOfElements);
for whatever value of numberOfElements. Given that the type of stck->symbols is struct table **, the type of the expression *(stck->symbols) will be struct table *. You could also write
malloc(sizeof (struct table*) * numberOfElements);
but I prefer the former method, as it minimizes the number of places you have to remember the type.
As this is C, you do not need to cast the result of malloc(), and it's considered poor practice to do so; if you forget to include stdlib.h or otherwise don't have a prototype for malloc() in scope, the cast will supress a warning alerting you to the problem (although since C99 no longer allows implicit int typing, that may no longer be an issue).

stck->symbols = baseaddress = malloc(...required total size...);
int nextDataLocation = baseAddress + numberOfRows*sizeof(void*);
for(int i=0; i<numberOfLines; i++)
{
stck->symbols[i] = nextDataLocation;
..copy string i to address stck->symbols[i]...
nextDataLocation += lengthOfString[i];
}

Related

How to make a custom size array in a struct in C

I have code like so
#ifndef hashtable
#define hashtable
// define the maxmium size
#define INITIAL_SIZE 5
#define LOAD_FACTOR 0.7
typedef struct hashtable
{
int keyArray[INITIAL_SIZE];
// 1d array of strings with maximum length 100 (plus '\0 character')
char valueArray[INITIAL_SIZE][100 + 1];
bool isActiveArray[INITIAL_SIZE]; // for deleting elements
int count;
int capacity;
double loadFactor;
// true: linear probing, false: quadratic probing
bool collisionHandler;
} table;
#endif
in hashtable.h file
in which I define a hashtable with a key array and value array and so on.
I am confused on how I could resize the hashtable, because whenever creating a new struct in order to resize, I fall into the problem that my INITIAL_SIZE cannot be changed, especially in a #define statement, although I want to make a new table that would have a capacity of 2*INITIAL_SIZE and so on ...
Here is my code of initTable() where I make the table incase it is helpful
void initTable(table* p, int size, double loadFactor, bool collisionHandler) {
// constructor
p->count = 0;
p->capacity = size;
p->loadFactor = loadFactor;
p->collisionHandler = collisionHandler;
memset( p->keyArray, 0, sizeof p->keyArray );
memset( p->valueArray, 0, sizeof p->valueArray );
memset( p->isActiveArray, 0, sizeof p->isActiveArray );
}
How can I resize the array, open to any suggestions even if removing INITIAL_SIZE entirely
Thanks for the help,
pew
Macros (defines) are not variables, they are replaced by their values before the compilation, so in your code all the INITIAL_SIZE will be replaced by 5.
When you declare a variable in your code, it will be statically allocated on the stack and its size is constant. you cant change the size of an array in a structure so you need to have the arrays outside of the structure and pointers that points to it like that:
typedef struct hashtable
{
int *keyArray;
char *valueArray;
bool *isActiveArray;
int count;
int capacity;
double loadFactor;
bool collisionHandler;
} table;
Then you will need to dynamically allocate the arrays with malloc. The malloc function take in argument the size that you want to allocate and return a pointer to the allocated area (on the heap).
for example:
table p;
int size = 5;
p.keyArray = malloc(size * sizeof(int)); // sizeof is a c operator that return the size of a type in bytes
if (p.keyArray == NULL) // it is a good practice to protect a malloc by checking its return value
exit(1);
//p.keyArray now points to an array of size 5, you can now use it like any other array
When you dont need the array anymore you must free the allocated memory with the free function
free(p.keyArray);
finally here is the full code to perform the resizing of an array:
void resize(int **array, int old_size, int new_size)
{
int *new_array = malloc(new_size * sizeof(int)); // allocate the new area
if (!new_array) // protect the malloc
exit(1);
memcpy(new_array, *array, old_size * sizeof(int)); // copy the content from the old area to the new one
free(*array); // free the old area
*array = new_array; // and change the pointer of the old area
}
or with realloc:
void resize(int **array, int new_size)
{
*array = realloc(*array, new_size * sizeof(int));
if (!*array)
exit(1);
}
edit:
as mentioned by Neil the realloc method is better because you let malloc do internal optimization (in case the area next to the initial area is sufficient it will just expand this area and this avoid to copy the content of the array). I just wanted to show you the malloc logic with the first version.
#jgiron42's answer is almost perfect using malloc to reallocate and using integer, char, and bool pointers for lists in hashtable.h, in my code/problem the only way to make it fully work was when copying a new key array of int* it needs to be done like so - > memcpy(new_keys, *keys, old_size * sizeof(int)); instead of what works for char and bool arrays memcpy(new_bools, *bools, old_size);

Writing to array of pointers in C

I need to write the pointer address of a struct (struct is called "Post") that has reposted another Post. There's a fixed return type called result with the following declaration:
struct result {
void** elements;
size_t n_elements;
};
For the Post struct, it has the following declaration:
struct post {
uint64_t pst_id;
uint64_t timestamp;
size_t* reposted_idxs;
size_t n_reposted;
};
Here's my code:
result* find_all_reposts(post* posts, size_t count, uint64_t post_id, query_helper* helper) {
result * ret_result = (result *) malloc(sizeof(result));
ret_result->elements[100];
ret_result->n_elements = 0;
for(int i = 0; i < count; i++){
post * temp = &posts[i];
size_t total_reposted = temp->n_reposted;
if(total_reposted > 0){
for(int q = 0; q < total_reposted; q++){
int index_of_repost = temp->reposted_idxs[q];
ret_result->elements[q] = &posts[index_of_repost];
ret_result->n_elements++;
}
}
}
return ret_result;
}
However I get a SEGV error for ret_result->elements[q] = &posts[index_of_repost];. I thought it could be originally that I hadn't initialised the elements field in the ret_result struct but I receive warning: statement with no effect for that:
warning: statement with no effect [-Wunused-value]- ret_result->elements[100];
I'm thinking that the void ** type for the elements field in result might be messing me around. From what I understand that's a pointer to a pointer which can obviously be an array and hence is basically a pointer to an array of posts?
I should clarify that count is the number of posts and that the returned-result is managed separately and hence any heap-allocated memory is freed in a separate process.
Thanks for your help :)
You haven't initialized ret_result->elements to anything. The statement ret_result->elements[100] is a no-op, the only reason you're not segfaulting there too is because your compiler is cutting it out. If you want that field to be a pointer to an array of size 100 you must initialize it with malloc. I'm not sure why you're declaring it to be a void ** double pointer here, but if it must be that way then something like this might work:
ret_result->elements = malloc(100 * sizeof(struct post *));
The call's arguments could also be 100 * sizeof(void *), but it might be a little what you intend to store there if you specify the struct to which the data will be pointing.

Simulating a List with array

Good morning!
I must handle a struct array (global variable) that simulates a list. In practice, every time I call a method, I have to increase the size of the array 1 and insert it into the new struct.
Since the array size is static, my idea is to use pointers like this:
The struct array is declared as a pointer to a second struct array.
Each time I call the increaseSize () method, the content of the old array is copied to a new n + 1 array.
The global array pointer is updated to point to a new array
In theory, the solution seems easy ... but I'm a noob of c. Where is that wrong?
struct task {
char title[50];
int execution;
int priority;
};
struct task tasks = *p;
int main() {
//he will call the increaseSize() somewhere...
}
void increaseSize(){
int dimension = (sizeof(*p) / sizeof(struct task));
struct task newTasks[dimension+1];
for(int i=0; i<dimension; i++){
newTasks[i] = *(p+i);
}
free(&p);
p = newTasks;
}
You mix up quite a lot here!
int dimension = (sizeof(*p) / sizeof(struct task));
p is a pointer, *p points to a struct task, so sizeof(*p) will be equal to sizeof(struct task), and dimension always will be 1...
You cannot use sizeof in this situation. You will have to store the size (number of elements) in a separate variable.
struct task newTasks[dimension+1];
This will create a new array, yes – but with scope local to the current function (so normally, it is allocated on the stack). This means that the array will be cleaned up again as soon as you leave your function.
What you need is creating the array on the heap. You need to use malloc function for (or calloc or realloc).
Additionally, I recomment not increasing the array by 1, but rather duplicating its size. You need to store the number of elements contained in then, too, though.
Putting all together:
struct task* p;
size_t count;
size_t capacity;
void initialize()
{
count = 0;
capacity = 16;
p = (struct task*) malloc(capacity * sizeof(struct task));
if(!p)
// malloc failed, appropriate error handling!
}
void increase()
{
size_t c = capacity * 2;
// realloc is very convenient here:
// if allocation is successful, it copies the old values
// to the new location and frees the old memory, so nothing
// so nothing to worry about except for allocation failure
struct task* pp = realloc(p, c * sizeof(struct task));
if(pp)
{
p = pp;
capacity = c;
}
// else: apprpriate error handling
}
Finally, as completion:
void push_back(struct task t)
{
if(count == capacity)
increase();
p[count++] = t;
}
Removing elements is left to you – you'd have to copy the subsequent elements all to one position less and then decrease count.

Freeing array of struct

I've done some research and couldn't find any answer to my problem.
I'm having problems with freeing my struct.
This is how i create my struct:
struct Structure * newStructure(int N)
{
struct Structure * structure;
int i;
structure = (struct Structure * ) malloc(N * sizeof(struct Structure));
for (i = 0; i < N; i++)
{
structure[i].i_Number = (int * ) malloc(sizeof(int));
structure[i].c_Char = (char * ) malloc(sizeof(char));
structure[i].c_Char[0] = '\0';
structure[i].d_Float = (double * ) malloc(sizeof(double));
}
return structure;
}
Everything works to this point. Later I fill every variable with random values so that they are not empty.
I call my freeMemory function like this freeMemory(structure, amountOfStructures);
And here is freeMemory function itself:
void freeMemory (struct Structure* structure, int N)
{
int i;
for( i=0 ; i<N ; i++ )
{
if (structure[i].i_Number!=NULL) free(structure[i].i_Number);
if (structure[i].c_Char!=NULL) free(structure[i].c_Char);
if (structure[i].d_Float!=NULL) free(structure[i].d_Float);
}
free(structure);
}
The free(structure) part works fine. But there are problems with the for loop and I have no idea what I'm doing wrong here.
#EDIT
I'm adding my struct declaration:
struct Structure{
int *i_Number;
char *c_Char;
double *d_Float;
};
#EDIT2
That's the function that initializes struct:
struct Structure* randomizing (int N)
{
struct Structure* structure = newStructure(N); int i;
srand(time(NULL));
for (i = 0; i < N; i++)
{
int _i; char _c; double _d;
_i = rand()%1000000;
_c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" [rand () % 26];
_d = 0;
setStructureNumber(structure, i,(int*) _i);
setStructureChar(structure, i, (char*) _c);
setStructureDouble(structure, i, &_d);
// I'VE COMMENTED OUT THE MUTATORS ABOVE AND THE ERROR DOES NOT SHOW ANYMORE, SO THERES SOMETHING WRONG WITH THEM
}
return structure;
}
And im calling it like this:
struct Structure* structure;
structure = randomizing(amountOfStructures);
The mutators used:
// Mutators
void setStructureNumber (struct Structure* structure, int p, int* num)
{
if (structure[p].i_Number != NULL) free(structure[p].i_Number);
structure[p].i_Number = (int*) malloc (sizeof(int));
structure[p].i_Number = num;
}
void setStructureChar (struct Structure* structure, int p, char* str)
{
if (structure[p].c_Char != NULL) free(structure[p].c_Char);
structure[p].c_Char = (char*) malloc (sizeof(char));
structure[p].c_Char = str;
}
void setStructureDouble (struct Structure* structure, int p, double* dou)
{
if (structure[p].d_Float != NULL) free(structure[p].d_Float);
structure[p].d_Float = (double*) malloc (sizeof(double));
structure[p].d_Float = dou;
}
The most likely reason is that somewhere in your code you go out of bounds of the memory you allocated and thus destroy the integrity of the heap. A frequently encountered practical manifestation of such undefined behavior is a failure at free, when the library detects the problem with the heap.
Inside you allocation cycle you allocate just one object of each respective type for each field of your struct object. For example, you allocate only one character for c_Char field and initialize it with \0. This might suggest that c_Char is intended to hold a string (is it?). If so, then the memory you allocated is sufficient for an empty string only. If you do not reallocate that memory later, any attempts to place a longer string into that memory will break the integrity of the heap and trigger undefined behavior.
The same applies to other fields as well. However, without extra explanations from you it is not possible to say whether it is right or wrong. At least, you have to provide the definition of struct Structure. And you have to explain your intent. Why are you dynamically allocating single-object memory for struct fields instead of just making these objects immediate members of the struct?
The additional code you posted is completely and utterly broken.
Firstly you are calling your mutators as
setStructureNumber(structure, i,(int*) _i);
setStructureChar(structure, i, (char*) _c);
setStructureDouble(structure, i, &_d);
This does not make any sense. Why are you trying to convert integer value _i to pointer type??? If you want to obtain a pointer to _i, it is done as &_i. You already do it correctly in the very last call, where you pass &_d. Why are the first two calls different from the last one? What was your logic behind this?
Secondly, inside your mutator functions
void setStructureNumber (struct Structure* structure, int p, int* num)
{
if (structure[p].i_Number != NULL) free(structure[p].i_Number);
structure[p].i_Number = (int*) malloc (sizeof(int));
structure[p].i_Number = num;
}
you are freeing old memory and allocating new memory. Why? Why don't just reuse the old memory to store the new value? (BTW, there's no need to check the pointer for null before calling free, because free will check it internally anyway.)
Thirdly, after allocating the new memory you immediately leak it by overriding the pointer value returned by malloc with the pointer value passed from the outside
structure[p].i_Number = num;
Again, this does not make any sense. This is actually what causes the crash on free - the pointers you pass from the outside are either meaningless random values (like your (int *) _i or (char *) _c)) or point to a local variable (like your &_d).
There's no way to "correct" your code without knowing what it is you are trying to do in the first place. There are just too many completely unnecessary memory allocations and reallocations and other illogical things. I would simply rewrite the mutator functions as
void setStructureNumber (struct Structure* structure, int p, int num)
{
*structure[p].i_Number = num;
}
Note - no memory reallocations and the argument is passed by value.
The functions would be called as
setStructureNumber(structure, i, _i);
setStructureChar(structure, i, _c);
setStructureDouble(structure, i, _d);
But again, this is so vastly different from what you have that I don't know whether this is what you need.
Technically, there is nothing wrong with what you are doing (except the missing error checks on allocations, unnecessary casts of malloc results, and unnecessary NULL checking before calling free).
This should work fine, assuming that you pass the correct value of N, and that you do not free things more than once:
struct Structure * newStructure(int N) {
struct Structure * structure = malloc(N * sizeof(struct Structure));
for (int i = 0; i < N; i++) {
structure[i].i_Number = malloc(sizeof(int));
structure[i].c_Char = malloc(sizeof(char));
structure[i].c_Char[0] = '\0';
structure[i].d_Float = malloc(sizeof(double));
}
return structure;
}
void freeMemory (struct Structure* structure, int N)
{
for(int i=0 ; i<N ; i++ )
{
free(structure[i].i_Number);
free(structure[i].c_Char);
free(structure[i].d_Float);
}
free(structure);
}
You can use a memory diagnostic tool such as valgrind to ensure that you do not freeing things more than once.
In your mutators you leak memory and then point to local variables (comments mine)
void setStructureChar (struct Structure* structure, int p, char* str)
{
if (structure[p].c_Char != NULL) free(structure[p].c_Char);
// allocates new memory and points c_Char at it.
structure[p].c_Char = (char*) malloc (sizeof(char));
// makes c_Char point to where `str` is pointing; now the allocated memory is leaked
structure[p].c_Char = str;
}
When you later do free on structure[p].c_Char, it causes undefined behaviour because you called this function with a pointer to a local variable. You probably have undefined behaviour elsewhere too if you try to access c_Char anywhere before freeing it.
The other mutators have the same problem.
To "fix" this change structure[p].c_Char = str; to *structure[p].c_Char = *str;.
You also have blunders here:
setStructureNumber(structure, i,(int*) _i);
setStructureChar(structure, i, (char*) _c);
You meant &_i and &_c respectively. I would advise to remove all casts from your code. At best they are redundant; at worst (e.g. in these two lines) they hide an error which the compiler would diagnose.
Also remove all the NULL checks before free, they are redundant and make your code hard to read. Instead, do the NULL checks after calling malloc, and abort the program if malloc returned NULL.
However this whole setup seems like a ghastly design. You could pass the things by value to the mutators. And you could change your struct to not contain pointers, and therefore not need all this extra allocation.

Data structure problem

I made a structure like so:
struct ponto {
int x;
int y;
int z;
};
1) Can I initialize the int's with a default value? int var = value; doesn't seem to work, compiler says "syntax error before '=' token" or something of sorts.
2) I need to work with several of these like in a array of structures, but I only know how many I need after the application starts up, after reading a file. How can I malloc this?
Thanks in advance
EDIT: So many answers, I'm grateful. Sadly I can only mark one
a) You can initalise with
struct pronto p = {1,2,3};
In recent compilers (not sure how portable this is, think it's C99?)
b) You can allocate an array with malloc:
struct pronto *array = malloc(sizeof(struct pronto) * NUMBER);
To initialize your structure members to 0, do:
struct ponto foo = { 0 };
To malloc() an array of the right size, do:
struct ponto *arr = (struct ponto *) malloc(COUNT * sizeof(struct ponto));
Don't forget to free() the array when you're done with it.
struct ponto* create_and_init_ponto(int n)
{
struct ponto* array;
int i;
array = (struct ponto*)malloc( n * sizeof(struct ponto) );
for ( i = 0; i < n; ++i )
{
array[ i ].x = 0;
array[ i ].y = 0;
array[ i ].z = 0;
}
return array;
}
You'e made a structure definition, now you have to create a variable of that structure before you can set the fields:
struct ponto xyz;
xyz.x = 7;
To allocate enough space:
int need_to_have = 24;
struct ponto *pontos = malloc (need_to_have * sizeof(struct ponto));
You cannot have "default" values for structure members. Space is not allocated for a structure definition. You're just creating a new type (like the inbuilt int). When you actually define a variable of type ponto, space will be allocated to it.
You can make an educated guess about how many you will need, allocate space for that many (using malloc) and go ahead. If you find that you're reaching the limit, you can use the realloc function to resize your array.
1) You cannot give a specific structure default values for its elements at the language level, because all variables in C are uninitialized unless you explicitly initialize them (or make them static/external in which case they're zero-initialized). If you design your structs such that all-zeros is a good set of initial values, though, you can always initialize like this:
struct foo myfoo = {0};
The {0} serves as a universal zero-initializer which works for any type.
If you need different defaults, the best way is to use a macro and document that code using your structure must use the macro:
#define FOO_INITIALIZER { 1, 2, 3 }
struct foo myfoo = FOO_INITIALIZER;
2) If you know before you start using any of the struct how many you will need, simply malloc them all once you know the number:
if (count > SIZE_MAX / sizeof *bar) abort();
struct foo *bar = malloc(count * sizeof *bar);
Note the proper idiom for calling malloc and avoiding overflow vulnerabilities.
If you don't know the number you'll need until you start working with them, start out by allocating a decent number, and if you run out, increase the number by a fixed multiple, for example doubling the size is common and easy. You'll want to check for overflows here. Then use realloc.
Question #1: If you need to initialize int with a value:
struct ponto p1;
p1.x = p1.y = p1.z = 3; // initializing with three
Alternatively, if you want to initialize all values to 0, you can use memset like this:
memset(&p1, 0, sizeof(struct ponto));
Question #2: To use malloc:
struct ponto *ps;
ps = (struct ponto *)malloc(N*sizeof(struct ponto));
// where N is your element count.
This will allocate memory to store N elements of type struct ponto. After that, you can initialize its values with:
int initvalue = 3; // assuming you want to initialize points with value 3
for (i=0; i<N; i++) {
ps[i].x = ps[i].y = ps[i].z = initvalue;
}

Resources