ratzip
ratzip

Reputation: 113

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?

Upvotes: 0

Views: 110

Answers (4)

Mr.C64
Mr.C64

Reputation: 42924

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

Upvotes: 0

Shahbaz
Shahbaz

Reputation: 47493

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.

Upvotes: 1

R Sahu
R Sahu

Reputation: 206567

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

Upvotes: 0

LearningC
LearningC

Reputation: 3162

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.

Upvotes: 0

Related Questions