How to allocate nested data structures with only one malloc call? - c

I would like to allocate nested data structures which are defined below with only one malloc call. Is it possible in C? If so, how can I do that?
struct s1 {
int a;
int b;
char ns1[16];
};
struct s2 {
struct s1 *ps1;
int i;
int j;
char ns2[16];
};

This is not a nested structure because ps1 is a pointer, not a structure.
malloc() works just fine with pointers. You can allocate s2 with no problem. But you will have to point the ps1 member to something valid.
A nested structure would look more like this:
struct s2 {
struct s1 x_s1;
int i;
int j;
char ns2[16];
};
And malloc() should be okay with that one as well.

A portable way to allocate space for multiple objects at once is to wrap them into a container structure:
struct PairHolder
{
struct s2 first;
struct s1 second;
};
// Postcondition: You own the result and must call free() on it (and on nothing
// else).
struct s2 * create_s2_and_s1()
{
struct PairHolder *ph = malloc(sizeof(PairHolder));
ph->first.ps1 = &ph->second;
return &ph->first;
}

After one day study, and based on previous answers. I came up with the solution below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct s1 {
int a;
int b;
char ns1[16];
};
struct s2 {
struct s1 *ps1;
int i;
int j;
char ns2[16];
};
int main(int argc, char *argv[])
{
struct s2 *ps2;
ps2 = malloc(sizeof(struct s1) + sizeof(struct s2));
ps2->ps1 = (struct s1 *)(ps2 + 1);
ps2->ps1->a = 1;
ps2->ps1->b = 2;
strcpy(ps2->ps1->ns1, "s1");
ps2->i = 3;
ps2->j = 4;
strcpy(ps2->ns2, "s2");
free(ps2);
return 0;
}

Related

EXC_BAD_ACCESS using QSort on an Array of Chars within Structs in C

I have searched through many of the answers on here and have implemented a few changes based on that, but am getting a EXC_BAD_ACCESS error when calling the qsort function. My IDE is pointing to the return in my qsort compare function as the problem. I know I am allocating memory properly for all the elements as I can print the strings with no problem if I omit the call to qsort. Could someone point me in the right direction?
My structs, to see how deep I am navigating:
typedef struct {
unsigned int siteId;
unsigned int tableTypeId;
unsigned int surMatId;
unsigned int strucMatId;
char *streetAve;
unsigned int neighbourhoodId;
char *neighbourhoodName;
unsigned int ward;
char *latitude;
char *longitude;
} Entries;
typedef struct {
int size;
Entries **entry;
} PicnicTable;
typedef struct {
Table *tableTypeTable;
Table *surfaceMaterialTable;
Table *structuralMaterialTable;
NeighbourHoodTable *neighborhoodTable;
PicnicTable *picnicTableTable;
} DataBase;
extern DataBase *DB;
Entries **ent = DB->picnicTableTable->entry;
qsort(ent,DB->picnicTableTable->size-1, sizeof(Entries*), cmpfunc); typedef struct {
unsigned int siteId;
unsigned int tableTypeId;
unsigned int surMatId;
unsigned int strucMatId;
char *streetAve;
unsigned int neighbourhoodId;
char *neighbourhoodName;
unsigned int ward;
char *latitude;
char *longitude;
} Entries;
typedef struct {
int size;
Entries **entry;
} PicnicTable;
typedef struct {
Table *tableTypeTable;
Table *surfaceMaterialTable;
Table *structuralMaterialTable;
NeighbourHoodTable *neighborhoodTable;
PicnicTable *picnicTableTable;
} DataBase;
extern DataBase *DB;
This is what the call looks like:
Entries **ent = DB->picnicTableTable->entry;
qsort(ent,DB->picnicTableTable->size-1, sizeof(Entries*), cmpfunc);
And the compare function is:
int cmpfunc(const void *a, const void *b) {
Entries *left = *(Entries**)a;
Entries *right = *(Entries**)b;
return strcmp(left->neighbourhoodName, right->neighbourhoodName);
}
The picnicTableTable, and Entry are initialized after this malloc:
DB->picnicTableTable = malloc(sizeof(PicnicTable));
DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);
DB->picnicTableTable->size = numEntries;
while ((c=fgetc(IN)) != EOF) {
if (c == ',' && row > 0) {
switch (column) {
case 0: neighbourhoodName = copyToChar(buff, begin, i);
...
}
copyToChar take a slice of the buffer and allocates memory then returns a pointer to a value that I assign:
char * copyToChar(const char * buff, int begin, int end) {
char *temp = malloc(end - begin + 1);
int j = 0;
for (int i = begin; i < end; i++, j++)
temp[j] = buff[i];
temp[j] = '\0';
return temp;
}
And the array is populated after I iterate through each row in a file (this is just one entry):
DB->picnicTableTable->entry[row]->neighbourhoodName = malloc(strlen(neighbourhoodName)*sizeof(char)+1);
The values of a->neighbourhoodName are NULL, which confuses me. Doesn't qsort pass two values from the array to the compare function?
Thanks for your time!
Beware. You declare entry to be a pointer to pointers (pointing to first element of an array of pointers)
typedef struct {
int size;
Entries **entry;
} PicnicTable;
but initialize it as a mere dynamic array, that is a pointer to first element of an array of Entrys in:
DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);
If you want an array of pointers to speed up qsort, you should build it separately:
typedef struct {
int size;
Entries *entry;
Entries **pentry;
} PicnicTable;
DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);
DB->picnicTableTable->pentry = malloc(numEntries*sizeof(&Entries)+1);
for (int i=0; i<=numEntries; i++) { // initialize the array of pointers
pentry[i] = entry + i;
}
Currently the definition of cmpfunc is not coherent with your initialization of DB->picnicTableTable->entry.

C array gets corrupted after being modified by a function

I'm trying to write a C program that gathers all structures passing a specific condition into an array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Book {
char title[20];
unsigned int published;
char authors[50];
unsigned int pages;
};
unsigned int get_books_from(unsigned int year, int length, struct Book data[], struct Book results[]);
int main(int argc, char* argv[]) {
struct Book data[5];
// Init book pool inside data
struct Book books[0];
unsigned int books_count = get_books_from(1973, 5, data, books);
return 0;
}
unsigned int get_books_from(unsigned int year, int length, struct Book data[], struct Book results[]) {
results = (struct Book*) malloc(sizeof(struct Book));
unsigned int results_count = 0;
int i;
for (i = 0; i < length; i++) {
if (data[i].published == year) {
*(results + results_count) = data[i];
results = (struct Book*) realloc(results, (++results_count + 1) * sizeof(struct Book));
}
}
return results_count;
}
The logic seems to be working fine, however when trying to access the books array contents outside of the get_books_from function (where it's called results), all the data becomes corrupted. Some of the original data is still there but not in the right places, it looks as if the data got shifted. I checked the pointers to both books and results and it appears that those variables do not point to the same place in memory after the function finishes. What could be the problem?
Your get_books_from changes the value of results here:
results = (struct Book*) realloc(results, (++results_count + 1) * sizeof(struct Book));
But it provides no way for the caller to get the new value of results.
Worse, you call get_books_from with data, which was allocated on the stack in main. You can't realloc it. As the documentation for realloc says, the pointer you are attempting to reallocate must been returned by a previous call to malloc, calloc, or realloc. Fortunately, you ignore that value. But that renders the struct Book data[5]; in main incomprehensible. Why allocate space on the stack?
In addition to the other answer:
You probably want something like this (untested, non error checking code, declarations and #includes ommited for brevity):
unsigned int get_books_from(unsigned int year, int length, struct Book data[], struct Book **results);
int main(int argc, char* argv[]) {
struct Book data[5];
// Init book pool inside data
struct Book *books;
unsigned int books_count = get_books_from(1973, 5, data, &books);
return 0;
}
unsigned int get_books_from(unsigned int year, int length, struct Book data[], struct Book **results) {
*results = (struct Book*) malloc(sizeof(struct Book));
unsigned int results_count = 0;
int i;
for (i = 0; i < length; i++) {
if (data[i].published == year) {
*(*results + results_count) = data[i];
*results = (struct Book*) realloc(*results, (++results_count + 1) * sizeof(struct Book));
}
}
return results_count;
}

How to assign an array to a struct in C

Say I have a simple struct, such as this one:
struct myStruct {
uint8_t arr[10];
};
All I want to be able to do is to modify the contents of that array. However, it seems that I cannot assign the array directly (ie, I can't do something like pointerToThisStruct->arr = anArrayofSizeTen).
So here is my main method:
int main(int argc, char **argv) {
uint8_t test[10] = {0};
myStruct *struc;
struc->arr = test; //can't do this
memcpy(struc->arr, test, sizeof(test));
}
Now, I understand that direct copying over won't work, but why is memcpy also giving me a segfault? How exactly am I supposed to modify the struct array?
You need to declare an actual myStruct. Not a pointer to one. Declaring a pointer to one doesn't actually allocate any memory for the struct.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
struct myStruct {
uint8_t arr[10];
};
int main(int argc, char **argv) {
int i;
uint8_t test[10] = {0,1,2,3,4,5,6,7,8,9};
struct myStruct struc;
memcpy(struc.arr, test, sizeof(struc.arr));
printf("struc.arr[] = ");
for( i=0; i < sizeof(test); i++ )
{
printf("%d ", struc.arr[i]);
}
printf("\n");
return( 0 );
}
You are getting a segmentation fault because you didn't allocate your struct pointer.
int main(int argc, char **argv) {
uint8_t test[10] = {0};
struct myStruct *struct = malloc(sizeof(struct myStruct));
if (!struc)
return -1;
memcpy(struc->arr, test, sizeof(test));
free(struc);
return 0;
}
But, as #Chimera mentioned, you perfectly can not use a point and directly a heap-allocated structure, and access to its inner fields with the . operator

How to allocate memory with different type in C?

I have the following code in C:
typedef struct
{
int age;
int phoneNumber;
} Student;
typedef struct
{
int id;
int student[1];
} People;
#define NUM_OF_PEOPLE
void *p = malloc(sizeof(People) + sizeof(int) * NUM_OF_PEOPLE + sizeof(Student) * NUM_OF_PEOPLE);
How could I find the pointer to the memory point to the first element of struct Student in the memory?
I try to do it in the following way:
int i = 0;
for(i = 0; i < NUM_OF_PEOPLE; i++)
{
Student * student_p = p.student[NUM_OF_PEOPLE];
}
It does not work, so can we allocate memory in the way?
And how to find the first element of struct Student in the memory?
What you have is an ancient way of having a flexible array member, which was technically also undefined behavior.
You are looking for this.
First, you need to define your struct like this (I don't know what the ints before the Students are, so let's just call it id):
typedef struct
{
int age;
int phoneNumber;
} Student;
typedef struct
{
int id;
Student student;
} StudentAndId;
typedef struct
{
int id;
StudentAndId students[];
} People;
Note the lack of size in the array inside People. Now you do this:
People *p = malloc(sizeof(People) + sizeof(StudentAndId[NUM_OF_PEOPLE]));
Then you can access students inside p as if it was an array of NUM_OF_PEOPLE elements.
Remember to compile with C99 (or C11) support. With gcc that would be -std=c99 or -std=gnu99.
This will allocate memory for storing the date but how you access it depends on how you store date. using C pointers you can store and access data using this structure and allocation but accessing the members will not be direct. it will involve pointer arithmetic. So better to use other structure if possible. If using this way of allocation then you need to do pointer arithmetic to get the next elements.
Try this:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int age;
int phoneNumber;
} Student;
typedef struct
{
int id;
int student[1];
} People;
#define NUM_OF_PEOPLE 10
int main()
{
People *p = malloc(sizeof(People) + sizeof(int) * NUM_OF_PEOPLE + sizeof(Student) * NUM_OF_PEOPLE);
int* id = (int*)(p+1);
Student* s = (Student*)(id+NUM_OF_PEOPLE);
printf("Size of People : %d\n", sizeof(People));
printf("p points to : %p\n", p);
printf("id points to : %p\n", id);
printf("s points to : %p\n", s);
}
Here's a sample output:
Size of People : 8
p points to : 0x80010460
id points to : 0x80010468
s points to : 0x80010490
You may want to add the id field to your Student data structure, e.g.:
typedef struct {
int id;
int age;
int phoneNumber;
} Student;
Then, you can define a structure having a fixed header (in this case, this can be the number of students), followed by a variable-sized array of Students:
#define ARRAY_OF_ANY_SIZE 1
typedef struct {
int count;
Student students[ARRAY_OF_ANY_SIZE];
} People;
This blog post explains this technique of having "arrays of size 1", including a discussion of the alignment problem.
I won't repeat the original blog post code here. Just consider that you can use the portable offsetof() instead of the Windows-specific FIELD_OFFSET() macro.
As a sample code, you may want to consider the following:
#include <stdio.h> /* For printf() */
#include <stddef.h> /* For offsetof() */
#include <stdlib.h> /* For dynamic memory allocation */
typedef struct {
int id;
int age;
int phoneNumber;
} Student;
#define ARRAY_OF_ANY_SIZE 1
typedef struct {
int count;
Student students[ARRAY_OF_ANY_SIZE];
} People;
int main(int argc, char* argv[]) {
People* people;
const int numberOfStudents = 3;
int i;
/* Dynamically allocate memory to store the data structure */
people = malloc(offsetof(People, students[numberOfStudents]));
/* Check memory allocation ... */
/* Fill the data structure */
people->count = numberOfStudents;
for (i = 0; i < numberOfStudents; i++) {
people->students[i].id = i;
people->students[i].age = (i+1)*10;
people->students[i].phoneNumber = 11000 + i;
}
/* Print the data structure content */
for (i = 0; i < people->count; i++) {
printf("id: %d, age=%d, phone=%d\n",
people->students[i].id,
people->students[i].age,
people->students[i].phoneNumber);
}
/* Release the memory allocated by the data structure */
free(people);
return 0;
}
Output:
id: 0, age=10, phone=11000
id: 1, age=20, phone=11001
id: 2, age=30, phone=11002

How to allocate a struct of struct?

So, I have a struct inside of other struct.. and I whant to know how I can malloc that struct...
#include <stdio.h>
#include <string.h>
struct
{
int n, o, p;
struct
{
int a, b, c;
}Str2;
}Str1;
main()
{
struct Str1.Str2 *x (Str1.Str2*)malloc(sizeof(struct Str1.Str2*));
x->a = 10;
}
So, I try that, but, not work..
How I can make this, Or is more better allocate all struct ?
You just need to allocate Str1 and Str2 would be allocated automatically. On my system, the sizeof for Str1 is 24 which equals to the size of 6 ints. Try this:
typedef struct {
int n;
int o;
int p;
struct {
int a;
int b;
int c;
}Str2;
}Str1;
main()
{
Str1 *x = (Str1 *)malloc(sizeof(Str1));
x->Str2.a = 10;
printf("sizeof(Str1) %d\n", (int)sizeof(Str1));
printf("value of a: %d\n", x->Str2.a);
}
Str1 and Str2 are objects of the anonymous structs you declared, so the syntax is way off. Did you forget some typedefs?
//declares a single object Str1 of an anonymous struct
struct
{
}Str1;
//defines a new type - struct Str1Type
typedef struct
{
}Str1Type;
To name a struct, you use
struct Str1
{
...
};
You can now use struct Str1 when you want to refer to this particular struct.
If you want to use it as Str1 only, you need to use typedef, e.g.
typedef struct tagStr1
{
...
} Str1;
Or typedef struct Str1 Str1; if we have the first type of struct Str1 declaration.
To create an instance of a struct with no name (Instance means "a variable of that type"):
struct
{
...
} Instance;
Since this struct doesn't have a name, it can't be used anywhere else, which is generally not what you want.
In C (as opposed to C++) you can not define a new type structure inside another the type definition of another structure, so
typedef struct tagStr1
{
int a, b, c;
typedef struct tagStr2
{
int x, y, z;
} Str2;
} Str1;
will not compile.
If we change the code to this:
typedef struct tagStr1
{
int a, b, c;
struct tagStr2
{
int x, y, z;
};
} Str1;
typedef struct tagStr2 Str2;
will compile - but at least gcc gives a warning for "struct tagStr2 does not declare anythign" (because it expects you wanted to actually have a member of type struct tagStr2 inside Str1.
Why not declare things like:
typedef struct
{
int a, b, c;
}Str2;
typedef struct
{
int n, o, p;
Str2 s2;
}Str1;
Then you can allocate them individually as you desire. For instance:
Str2 *str2 = (Str2*)malloc(sizeof(Str2));
Str1 *str1 = (Str1*)malloc(sizeof(Str1));
s1->s2.a = 0; // assign 0 to the a member of the inner Str2 of str1.

Resources