So I have an array of structs with every struct containing a dynamic array of strings.
typedef struct _test {
int total;
char *myarray[];
} Test;
This how I allocated enough memory
Test *mystruct = (Test *)malloc(size);
Above is how my struct is formated
mystruct[x].myarray[index] = strdup(name);
index++;
mystruct[x].total = index;
when trying to access a string in that array i.e. :
printf("%s", mystruct[0].myarray[0]);
Nothing prints, thanks for any help!
The following is correct. I'll explain below.
typedef struct TEST {
int total;
char *myarray[];
} Test;
int StackOveflowTest(void)
{
int index;
Test *mystruct = malloc(sizeof(Test)+10*sizeof(char *));
for (index=0; index<10; index++)
mystruct->myarray[index] = strdup("hello world");
mystruct->total = index;
for (index=0; index<10; index++)
printf("%s\n", mystruct->myarray[index]);
return 0;
}
Actually, you declare an "array of pointers" myarray, however that array has zero elements. This "trick" is used to have the ability that at the end of the struct you have an array of variable size when malloc'ing the array:
Test *mystruct = malloc(sizeof(Test)+10*sizeof(char *));
This allocates the size of the struct and adds room for 10 array elements.
Since you did not allocate this flexible part of the struct, you wrote into "nothing" and are lucky the program did not abort (or it did, which is why there was no output).
P.s.: don't forget to free the memory when you are done:
for (index=0; index<10; index++)
free(mystruct->myarray[index]);
free(mystruct);
Related
I need to have a global dynamic array of pointers, in which I will store my structs, beacuse later I will need to iterate through this array to list all the stored information, I also need to be able to read the name, age and job variables from the console, and store them in a person_t in the iterator array.
#include <stdio.h>
#include <stdlib.h>
typedef struct Person
{
char name[30];
int age;
char job[30];
} person_t;
person_t **iterator;
int capacity = 10;
int size = 0;
int main()
{
int i;
*iterator = (person_t *)malloc(capacity * sizeof(person_t));
for (i = 0; i < capacity; ++i)
{
person_t p;
p.age = i;
*iterator[i] = p;
}
return 0;
}
I get no errors/warnings compiling this code (gcc -ansi -pedantic -Wall -Wextra), but when I try to run it, I get a Segmentation fault immediately.
When you do this:
*iterator = (person_t *)malloc(capacity * sizeof(person_t));
You're deferencing iterator, however as a file-scope pointer variable it's initialized to NULL. Attempting to dereference a NULL pointer invokes undefined behavior.
I suspect what you really want is an array of structs, not an array of pointers to structs. That being the case, define iterator as:
person_t *iterator;
Then you allocate memory for it like this:
iterator = malloc(capacity * sizeof(person_t));
Then assign to array elements like this:
iterator[i] = p;
Your stated purpose is to create a "global dynamic array of pointers, in which I will store my structs". The following modification of your code (see comments) will do this:
person_t p[10] = {0};
int main()
{
int i;
// with declaration: person_t **iterator = NULL;,
//following is all that is needed to create an array of pointers:
iterator = malloc(capacity * sizeof(person_t *));//no need to cast return of malloc
for (i = 0; i < capacity; ++i)
{
//person_t p;//moved to scope that will exist outside of main()
p[i].age = i;
iterator[i] = &p[i];//assign the address of the object to the pointer
//iterator[i] is the ith pointer in a collection of
//pointers to be assigned to point to
//instances of struct person_t
}
//Once all fields are populated (to-do), the following will display the results:
for (i = 0; i < capacity; ++i)
{
printf("%d) Name: %s Age: %d Job: %s\n", i, iterator[i]->name,iterator[i]->age,iterator[i]->job);
}
return 0;
}
you are not allocating memory correctly
First you need to allocate memory for a pointer which can store capacity number of address i.e done through iterator = malloc(capacity * sizeof(person_t*)); and then you need to allocate memory for holding each structure element i.e iterator[i] = malloc(sizeof(person_t));
all the malloc'ed memory should be free'd once we are done with it.
Also, have not done the error check for malloc's , that is left as an exercise for you.
int main()
{
int i;
// test data
char *names[] = {"ABC", "DEF"};
char *jobs[] = {"Accountant", "Security"};
int ages[] = {50, 60};
// first allocate memory for iterator , which can hold pointers to store iterator poniters
iterator = malloc(capacity * sizeof(person_t*));
for (i = 0; i < capacity; ++i)
{
// now allocate memory for individual iterator
iterator[i] = malloc(sizeof(person_t));
strcpy(iterator[i]->name,names[i]);
iterator[i]->age = ages[i];
strcpy(iterator[i]->job, jobs[i]);
}
for (i = 0; i < capacity; ++i)
{
printf("name = %s ", iterator[i]->name);
printf("Age = %d ", iterator[i]->age);
printf("Job = %s\n", iterator[i]->job);
}
return 0;
}
this is how i declare this struct
typedef struct cache{
int vaild;
char* tag;
char* data;
}cache;
this is part of my main which called this function
struct cache **cacheA = createCache(Setnum,(int)pow(2,blocksize),cachesize);
struct cache **cacheB = createCache(Setnum,(int)pow(2,blocksize),cachesize);
and now this is my called function
struct cache ** createCache(int numset, int blocksize, int cachesize){
int numcache = (int)((cachesize/blocksize)*numset);
struct cache out[numset][numcache];
int i,j;
for (i=0; i < numset; i++){
for (j=0; j < numcache; j++){
out[i][j].tag = "0";
out[i][j].vaild = 0;
out[i][j].data ="0";
}
}
return out;
}
and when i try to compile this, it tells me that
return from incompatible pointer type
function returns address of local variable
(which points to the line "return out;")
I have no idea whats wrong with my code, i mean the type of the function return is the same as how i declear "out", so what causes this problem?
You create struct cache out[numset][numcache];
within the function prototyped as: struct cache ** createCache(...).
Then attempt to return out.
It is because struct cache [][] is typed differently than struct cache ** that you are getting the return errors.
Other comments:
1) If you truly do want a pointer to pointer to struct, then malloc or calloc will need to be used at some point to allocate memory.
2) the char * members of the struct also need to be assigned memory before assigning values. For illustration below, they are changed to char []
3) assigning values to strings does not work by using = assignment operator. Use a string function such as strcpy, sprintf, etc.
4) you've named the struct with the same symbol as that of the new type you have created, i.e. cache. In this application, the name cache is not necessary. Also, purely for style, I show the new type in CAPS. This is not necessary, but just a style I use to make the new type more recognizable in code.
In consideration of the comments above, the struct could be changed to the following:
typedef struct { /// don't need name here when it in this application
int vaild;
//char *tag;
char tag[20];//for illustration, to avoid additional dynamic allocation of memory
//char* data;
char data[80];
}CACHE;//capitalization is style only, not a necessity here.
Note, there is no name, but the new type CACHE was created. Now, you can create the function createCache:
CACHE ** createCache(int ncache, int nset)//note for simplicity of freeing this
//object later, simplify number of arguments
{
CACHE **out;
out = calloc(ncache, sizeof(CACHE *));//create array of pointers to CACHE
if(!out) return NULL;
int i;
for (i=0; i < nset; i++)
{
out[i] = calloc(nset, sizeof(CACHE));//create space for each instance
//of CACHE pointed to by array pointers
}
return out;
}
Anytime memory is created on the heap, it needs to be freed. This method will free the CACHE object memory:
void freeCashe(CACHE **a, int nset)
{
int i;
for(i=0; i<nset; i++)
{
if(a[i])free(a[i]);
}
if(a)free(a);
}
Calling these functions as shown below, will create an array of pointers, each pointing to an instance of CACHE where you can use them as intended, then free all of the memory when finished:
int main(void)
{
int cachesize = 20;
int blocksize = 20;
int numset = 10;
//move the calculation out of creation function
//to simplify freeing object later.
int numcache = (int)((cachesize/blocksize)*numset);
CACHE **a = createCache(numcache, numset);
/// use a, then free a
freeCashe(a, numset);
return 0;
}
Your function needs to allocate the memory on the heap rather than the stack. You will need to allocate space on the heap for your array of pointers, and for what they point too.
struct cache ** createCache(int numset, int blocksize, int cachesize){
cache ** out;
int numcache = (int)((cachesize/blocksize)*numset);
size_t headerSize = sizeof(*out)*numset;
size_t bodySize = sizeof(**out)*numcache;
out = malloc(headerSize + (bodySize*numset));
if (out == NULL) {
/* Should probably output some message about being
* insufficient memory here. */
return NULL;
}
int i,j;
for (i=0; i < numset; i++){
/* need to assign our point */
out[i] = (cache*)(((char*)out)+(headerSize+bodySize*i));
for (j=0; j < numcache; j++){
out[i][j].tag = "0";
out[i][j].vaild = 0;
out[i][j].data ="0";
}
}
return out;
}
/* importantly, you want a way to free your allocated memory */
void destroyCache(cache ** ptr) {
free(ptr);
}
PS: You don't have to typedef your struct if you reference it with the struct keyword.
You are wanting a pointer pointer type to be returned, but in order to do that you need to dynamically allocate it. Local stack allocations (i.e. struct cache[x][y]) won't work. You will either get an error or your program will crash when attempting to use the 2D array.
The solution is to either pre-allocate space and pass it in to the function or allocate in the function itself.
Allocation In Function Example:
struct cache ** createCache(int numset, int blocksize, int cachesize){
int numcache = (int)((cachesize/blocksize)*numset);
struct cache **out = malloc(sizeof(struct cache *) * numset); // This line changed.
int i,j;
for (i=0; i < numset; i++){
out[i] = malloc(sizeof(struct cache) * numcache); // This line added.
for (j=0; j < numcache; j++){
out[i][j].tag = malloc(sizeof(char)); // This line added.
out[i][j].data = malloc(sizeof(char)); // This line added.
strcpy(out[i][j].tag, "0");
out[i][j].vaild = 0;
strcpy(out[i][j].data, "0");
}
}
return out;
}
typedef struct
{
char *s;
char d;
}EXE;
EXE *p;
For the above struct how do I initialize the structure with pointer? I know for a non-pointer we do EXE a[] = { {"abc",1}, {"def",2} }; . Similarly Is it possible with a pointer after allocating the memory? Say like p[] = { {"abc",1},.. so on} . Basically I want to initialize dynamically. Thanks.
We can initialise the structure with pointer as below
example:
int i;
char e[5]="abcd";
EXE *p=malloc(sizeof(*p));
for(i = 0;i < 5;i++)
*(p+i)=(EXE){e,i+48};
First you need to allocate some memory for that char * and after that use strcpy library function to copy data for structure element.
p->s = strcpy(s,str); //where str source, from where you need to copy the data
I hope this will help. Though I can give you full code for that, But I want you to try.
You can use this
Dynamically allocate C struct?
and it is a duplicate question.
You have to understand how do allocated pointer works:
Suppose you've allocated memory for three structs Ptr = malloc(3*sizeof(EXE)).
Then when you add 1 to Ptr, it comes to the next struct. You have a block of memory divided by 3 (3 smaller blocks of memory for each struct).
So, need to access to the elements of the 1st struct and then move the pointer to the next one.
Here you can understand how it works:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char *s;
char d;
} EXE;
int main()
{
int i;
EXE *Ptr;
Ptr = malloc(3*sizeof(EXE)); // dymnamically allocating the
// memory for three structures
Ptr->s = "ABC";
Ptr->d = 'a';
//2nd
Ptr++; // moving to the 2nd structure
Ptr->s = "DEF";
Ptr->d = 'd';
//3rd
Ptr++; // moving to the 3rd structure
Ptr->s = "XYZ";
Ptr->d = 'x';
//reset the pointer `Ptr`
Ptr -= 2; // going to the 1st structure
//printing the 1st, the 2nd and the 3rd structs
for (i = 0; i < 3; i++) {
printf("%s\n", Ptr->s);
printf("%c\n\n", Ptr->d);
Ptr++;
}
return 0;
}
Notice:
- If you have a variable of a struct use . opereator to access to the elements.
- If you have a pointer to a struct use -> operator to access to the elements.
#include <stdio.h>
#include <stdlib.h>
struct EXE {
int a;
};
int main(){
struct EXE variable;
struct EXE *pointer;
pointer = malloc(sizeof(struct EXE)); // allocating mamory dynamically
// and making pointer to point to this
// dynamically allocated block of memory
// like here
variable.a = 100;
pointer->a = 100;
printf("%d\n%d\n", variable.a, pointer->a);
return 0;
}
I have this struct:
struct sArray {
TCHAR *sName;
};
I want to now dynamically allocate memory for an array of sArray, and also dynamically allocate memory for sName. So I can use something like var[0].sName, var[1].sName...var[x].sName.
I'm looking for a simple solution - tons of articles here and on the web about dynamic allocation, but none answer this.
So, how do I do this? And how do I free the member and array memory when done with them?
Try this:
int len = 20; //number of elements (sArray's) you want in ar.
struct sArray *arr = malloc(length*sizeof(struct sArray));
int i;
int nameLength = 30; // max length of name
for (i = 0; i < length; ++i)
arr[i].sName = malloc(nameLength*sizeof(TCHAR));
and to free the memory:
for (i = 0; i < length; ++i)
free(arr[i].sName);
free(arr);
// +1 for the NULL terminal byte
TCHAR *names = (TCHAR *)calloc(1, (maxNameLen+1) * NumberOfNames);
struct sArray *array = (struct sArray *)malloc(numberOfArrays);
array[0].sName = names[0];
...
...
free(names);
free(array);
I am trying to pass a structure array pointer and a pointer to a structure array pointer into a function and then have it modified rather than using a return.
This example code is indeed pointless, its just a learning example for me.
Basically I want to create array[0]...array[1]..array[2] and so on and have a pointer that points to these while using a different index...such as array_ref[2] points to array[0] and array_ref[3] points to array[1].
The code below compiles, but immediately crashes. Any suggestions?
typedef struct unit_class_struct {
char *name;
char *last_name;
} person;
int setName(person * array, person ***array_ref) {
array[0].name = strdup("Bob");
array[1].name = strdup("Joseph");
array[0].last_name = strdup("Robert");
array[1].last_name = strdup("Clark");
*array_ref[2] = &array[0];
*array_ref[3] = &array[1];
return 1;
}
int main()
{
person *array;
person **array_r;
array = calloc (5, sizeof(person));
array_r = calloc (5, sizeof(person));
setName(array,&array_r);
printf("First name is %s %s\n", array_r[2]->name, array_r[2]->last_name);
printf("Second name is %s %s\n", array_r[3]->name, array_r[3]->last_name);
return 0;
}
You are allocating an array of structures but declaring an array of pointers.
Calloc() and malloc() return a void * object that can be assigned to everything. So, even with -Wall your program will compile with no warnings.
However, when it runs, it tries to deal with what you said was an array of pointers, in fact, an array of pointers to pointers to pointers. None of these pointers are ever created. All you start with are one-level pointers to an array of objects. Depending on what you really want, you may need something more like...
array_ref[2] = &array[0];
array_ref[3] = &array[1];
return 1;
}
int main()
{
person *array, *array_r_real;
person **array_r;
array = calloc(5, sizeof(person));
array_r_real = calloc(5, sizeof(person));
array_r = calloc(5, sizeof(struct unit_class_struct *));
int i;
for (i = 0; i < 5; ++i)
array_r[i] = &array_r_real[i];
setName(array, array_r);