initializing structures and nesting structures - c

gcc
I am just getting back into c programming and I am just practicing with structures. However, I have a nested structure that I want to fill from another initialized structure. However, I don't think my technique is correct way to do this.
Any advice would be most helpfull,
#include <stdio.h>
typedef struct
{
char name[20];
int age;
} NAME_AGE_STRUCT;
typedef struct
{
int ID;
NAME_AGE_STRUCT info[];
} DETAILS_STRUCT;
int main(void)
{
DETAILS_STRUCT details;
NAME_AGE_STRUCT extra_details [] = {
{ "john", 34 },
{ "peter", 44 },
};
printf("=== Start program\n");
details.ID = 2;
details.info = extra_details;
return 0;
}

You need to specify a length of the array in the DETAILS_STRUCT; otherwise there's no memory to assign into. If you want to have an arbitrary array there, declare it as a pointer instead:
typedef struct
{
int ID;
NAME_AGE_STRUCT *info;
} DETAILS_STRUCT;

Related

failing freeing dynamic struct array in c

I'm having some problem with freeing dynamic struct array and I can't understand why.
first of all there is this struct:
typedef struct
{
char name[LEN];
char address[MAX];
} Airport;
And the constructor I made for this struct isn't using allocation for this struct building.
sec of all there is this struct:
typedef struct
{
Airport* airports;
int maxAPS;
int currentAPS;
} AirportManager;
//constructor
void addAirport(AirportManager* pAirportManager)
{
if (pAirportManager->maxAPS == pAirportManager->currentAPS)
{
pAirportManager->maxAPS++;
pAirportManager->airports = (Airport*)realloc(pAirportManager->airports, sizeof(Airport)*pAirportManager->maxAPS);
//pAirportManager->airports[pAirportManager->currentAPS] = *(Airport*)malloc(sizeof(Airport));
}....
and when I'm ending my program and want to free the AirportManager with the following code:
void freeAirportManager(AirportManager* pAirportManager)
{
for (int i = 0; i < pAirportManager->currentAPS; i++)
free(&pAirportManager->airports[i]);
free(pAirportManager->airports);
}
I've debuged this one and all the parameters are just fine but after one run in the loop the program exits, what should I change in the free function ?
do I need the marked line in the constructor ? I just added this on thinking it might help, but seems to not work as well... do I need to free only the array itself ?
for (int i = 0; i < pAirportManager->currentAPS; i++)
free(&pAirportManager->airports[i]);
You need only to free pAirportManager->airports. You do not have pointer to pointer here.
So instead of those two lines:
free(pAirportManager->airports);
I would use flexible array member instead of pointer.
typedef struct
{
char name[LEN];
char address[MAX];
} Airport;
typedef struct
{
size_t maxAPS;
size_t currentAPS;
Airport airports[];
} AirportManager;
For sizes use size_t type instead of int

Passing strings through and array to a struct in C

I'm pretty new to C and I'm not sure what I'm doing. Im trying to create a simple function to create a book. I want to pass two strings in as parameters but I don't know the proper way to access them in C. I have tried many things here is where I am at. Thanks for any help!
#include <stdio.h>
struct book {
char title[50];
char author[50];
};
struct book createBook(char title[50], char author[50]) {
struct book x = { title, author };
return x;
}
You won't be able to initialize the members this way since they're strings.
Use strncpy from string.h:
#include <string.h>
strncpy(x.title, title, 50);
strncpy(x.author, author, 50);
And your declaration would just become:
struct book x;
Use can't initialize variable or members using this way struct book
x = { title, author };
use strcpy() or strncpy() for initializing member variables
strncpy_s(x.title, "Kite Book",sizeof(x.title));
strncpy_s(x.author, "Andre",sizeof(x.author));
or
strcpy(x.title, "Kite Book");
strcpy(x.author, "Andre");
#include <stdio.h>
#include<string.h>
struct book {
char title[50];
char author[50];
};
struct book createBook(char title[50], char author[50]) {
struct book x;
strncpy_s(x.title, "Kite Book",sizeof(x.title));
strncpy_s(x.author, "Andre",sizeof(x.author));
return x;
}
int main()
{
char title[] = { "Kite" };
char author[] = { "Andre" };
createBook(title, author);
return 0;
}

initializing a struct array with array inside

So I made a struct with a with an uninitialized array inside but the outer struct is an array that is initialized. I then loop through and print the values but I'm not getting anything. NUM is already defined as 12.
#include "header.h"
#include <stdio.h>
#include <stdlib.h>
void make() {
struct suit {
char *type;
int people[];
} deck[4] = {"Hunter", NUM,
"Fighter", NUM,
"Jumper", NUM,
"Strider", NUM};
};
//print type and numbers 1-12
for (int i = 0; i < 4; i++) {
for (int j = 0; j < NUM; i++) {
printf(deck[i].type);
printf(deck[i].people[j]);
}
}
}
Allocate the memory of int people[]; array, So, your struct should look like this, since it is an object definition:
struct suit {
char *type;
int people[10]; //compile time allocation
} deck[4] = {"Hunter", NUM,
"Fighter", NUM,
"Jumper", NUM,
"Strider", NUM};
people is a flexible array member and Standard C does not allow initialization of flexible array member. Though, GCC allows static initialization of flexible array as an extension. So,
struct suit {
char *type;
int people[];
} deck = {"Hunter", NUM};
is valid snippet as per GCC, but at the same time GCC doesn't allow nested array initialization when flexible array member is involved and therefore the initializer for deck[4] is not valid.
Of course, this extension only makes sense if the extra data comes at the end of a top-level object, as otherwise we would be overwriting data at subsequent offsets. To avoid undue complication and confusion with initialization of deeply nested arrays, we simply disallow any non-empty initialization except when the structure is the top-level object. For example:
struct foo { int x; int y[]; };
struct bar { struct foo z; };
struct foo a = { 1, { 2, 3, 4 } }; // Valid.
struct bar b = { { 1, { 2, 3, 4 } } }; // Invalid.
struct bar c = { { 1, { } } }; // Valid.
struct foo d[1] = { { 1, { 2, 3, 4 } } }; // Invalid.
Also note that you should use appropriate format specifiers in printf for different data types.

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

Access element of array of pointer of structure

I want to access the element of array of pointer to structure but i have no idea how to access it.
#include<stdio.h>
int main()
{
struct hash
{
int pages;
int price;
};
struct hash *h[5]={1,2,3,4,5};//array of pointer to structure
printf("value =%d\n",h->pages);
// want to access and also tell me how to data will be write
}
How we will access the element I tried it through pointer but it's showing error
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct hash {
int pages;
int price;
};
struct hash *h[2];
h[0] = malloc(sizeof(struct hash));
h[0]->pages = 1;
h[0]->price = 2;
h[1] = malloc(sizeof(struct hash));
h[1]->pages = 3;
h[1]->price = 4;
printf("value = %d\n", h[0]->pages);
}
Here is a sample that compiles. Maybe this helps you get started.
#include <stdio.h>
#include <stdlib.h>
struct hash
{
int pages;
int price;
};
struct hash h[5]=
{
{ 1, 1 },
{ 2, 2 },
{ 3, 3 },
};
int main(void)
{
printf("pages: %d\n", h[0].pages);
printf("pages2: %d\n", h[1].pages);
return EXIT_SUCCESS;
}
I would first suggest trying to get a stuct hash *h; to point to a single variable. Once that works, you should build upon it to get the array of struct hash *h[5] to work.

Resources