'Access the int value of the nested struct in C
I can access the char value of the nested struct, but the int one it shows memory address only, how I can dereference the pointer value of an int one ? here is a sample code:
#include <stdio.h>
struct Class {
char name[10];
int cap;
};
struct Student {
char firstname[10];
char lastname[10];
struct Class *class[5];
};
void printStudents(struct Student *student) {
struct Class *class;
class = student->class[2];
printf("Capacity => %d\n", &class->cap);
printf("Class => %s\n", &class->name);
}
int main(void) {
struct Class class[] = {
{"rust", 8},
{"python", 22},
{"java", 33}
};
struct Student student = {"Ian", "saeidi", (struct Class *) &class};
struct Class class[] = {
{"rust", 8},
{"python", 22},
{"java", 33}
};
struct Student student = {"Ian", "saeidi", &class};
printStudents(&student);
return 0;
}
Output:
Expected Output:
Capacity => 33
Class => java
I have tried the below initialization still does not worked, and the editor says that it is element 0, while I have added the entire struct array:
struct Class class[] = {
{"rust", 8},
{"python", 22},
{"java", 33}
};
struct Student student = {"Ian", "saeidi", (struct Class *) &class};
struct Class class[] = {
{"rust", 8},
{"python", 22},
{"java", 33}
};
struct Student student = {"Ian", "saeidi", &class};
Solution 1:[1]
struct Student student = {"Ian", "saeidi", {"rust", 24}}; is incorrect. The {"rust", 24} part needs to be changed to a pointer to a struct Class. That struct Class could be stored as a variable like this:
struct Class class = {"rust", 24};
struct Student student = {"Ian", "saeidi", &class};
Alternatively, that struct Class could be stored as a compound literal like this:
struct Student student = {"Ian", "saeidi", &(struct Class){"rust", 24}};
A compound literal behaves rather like an initialized variable, but is anonymous.
The printStudents function is passing the wrong arguments to printf(). It is passing the address of class->cap instead of the value of class->cap. And it is also passing the address of class->name instead of the the address of class->name[0]. That can be corrected by removing the & from both calls to printf:
printf("Capacity => %d\n", class->cap);
printf("Class => %s\n", class->name);
N.B. class->name is the same value as &class->name[0].
EDIT after OP changed the question
OP changed struct Student member class from struct Class *class to struct Class *class[5]. The previous initialization should still work, but student.class[1] through to student.class[4] will have the default initialization of NULL.
With OP's array of 3 classes, student can be initialized as follows:
struct Class class[] = {
{"rust", 8},
{"python", 22},
{"java", 33}
};
struct Student student = {"Ian", "saeidi",
{ &class[0], &class[1], &class[2] } };
Full working code:
#include <stdio.h>
#define ARRAY_LEN(x) (sizeof (x) / sizeof *(x))
struct Student {
char firstname[10];
char lastname[10];
struct Class *class[5];
};
struct Class {
char name[10];
int cap;
};
void printStudents(struct Student *student) {
printf("First name => %s\n", student->firstname);
printf("Last name => %s\n", student->lastname);
for (int i = 0; i < ARRAY_LEN(student->class); i++) {
struct Class *class = student->class[i];
if (class) {
printf("Class %d =>\n", i);
printf(" Capacity => %d\n", class->cap);
printf(" Name => %s\n", class->name);
}
}
}
int main(void) {
struct Class class[] = {
{"rust", 8},
{"python", 22},
{"java", 33}
};
struct Student student = {"Ian", "saeidi",
{ &class[0], &class[1], &class[2] } };
printStudents(&student);
return 0;
}
Solution 2:[2]
You have several problems:
- You're not allocating any space for
class, so trying to initialize it with{"rust", 24}is incorrect. - Even if that was ok,
nameis a singlecharand cannot hold nor point to a string. - Since the initialization is wrong,
class = student->class;assignsclassto invalid memory, and dereferencing it (class->) invokes undefined behavior. "%d"printfformat specifier expects anint, but you pass it anint*"%s"printfformat specifier expect achar*, but you pass it achar (*)[10](pointer to a 10 sizechararray).
One possible fix:
// flip the order of the structs so you can declare a `struct Class class` in
// `struct Student` (no pointer)
struct Class {
// change this from a pointer to array
char name[10];
int cap;
};
struct Student {
char firstname[10];
char lastname[10];
struct Class class;
};
void printStudents(struct Student *student) {
// get a pointer to the address of student->class if you want
struct Class *class;
class = &(student->class);
// now things print appropriately
// pass an `int` to %d
printf("Capacity => %d\n", class->cap);
// pass a `char*` to %s. `class->name` in this context "decays" to a
// pointer to its first element, a `char`
printf("Class => %s\n", class->name);
}
int main(void) {
// now your initialization is valid
struct Student student = {"Ian", "saeidi", {"rust", 24}};
printStudents(&student);
return 0;
}
You could also use dynamic memory allocation instead of arrays.
EDIT after OP changed the question, another possible implementation. See explanation comments below:
struct Class {
char name[10];
int cap;
};
struct Student {
char firstname[10];
char lastname[10];
// Not exactly sure what you're trying to do, but I've changed your
// pointer here to be a pointer to an array of three `struct Class`es
// (since that's what you're creating in main, and so this is the only
// compatible pointer that can point to such an object).
struct Class (*class)[3];
};
void printStudent(struct Student *student) {
struct Class (*class)[3];
class = (*student).class;
// Take note of the pointer arithmetic here. class+1 advances the
// pointer the size of three `struct Class`es. From main, there's
// only one object of this type (three `struct Class`es), so you
// have to dereference the pointer at that first object only
// (eg, `(*class)` ), then apply the index for `cap` and `name`.
// If you do `class[i]`, for `i>0` you point to the `i`th object of
// 3 `struct Class`es, which of course don't exist. There's only one.
for (size_t i=0; i<3; i++)
{
printf("Capacity => %d\n", (*class)[i].cap);
printf("Class => %s\n", (*class)[i].name);
}
}
int main(void) {
// here you're creating three `struct Class`es
struct Class class[] = {
{"rust", 8},
{"python", 22},
{"java", 33}
};
// pass the address of `class` to your struct. This type is a
// struct Class (*)[3]. That is, a pointer to a 3-size array of
// struct Class type. If you added or subtracted another entry
// to your class definition above, then you'd have to change the
// pointer dimension in struct Student as well.
struct Student student = {"Ian", "saeidi", &class};
printStudent(&student);
return 0;
}
Solution 3:[3]
I have found the problem, the class array length should be determine during initialization:
#include <stdio.h>
struct Class {
char name[10];
int cap;
};
struct Student {
char firstname[10];
char lastname[10];
struct Class *class;
};
void printStudents(struct Student *student) {
struct Class *class;
class = student->class[2];
printf("Capacity => %d\n", &class->cap);
printf("Class => %s\n", &class->name);
}
int main(void) {
// here I added the length of the class struct
struct Class class[5] = {
{"rust", 8},
{"python", 22},
{"java", 33}
};
struct Student student = {"Ian", "saeidi", &class};
printStudents(&student);
return 0;
}
@ian abbott and other guys, Thanks for participating
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | mos |


