How to allocate a struct of struct? - c

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.

Related

Defining a program local pointer of a structure

my question deals with creating variables that are visible throughout the program file. In other words, a file-local variable.
Consider this example
#include <stdio.h>
struct foo
{
char s[] = "HELLO";
int n = 5;
};
struct foo *a;
int main()
{
puts("Dummy outputs!\n");
printf("%s\n",a->s);
printf("%d\n",a->n);
return 0;
}
Now, this code snippet won't run.
Why?
Because the structure pointed to be pointer variable a will not get allocated as the statement never executed.
Now, how do you get it allocated without changing the scope of this variable a?
#include <stdio.h>
struct foo {
char const *s;
int n;
};
/* static for file-local */
static struct foo a = { "HELLO" , 5 };
int main(void) {
printf("%s\n", a.s);
printf("%d\n", a.n);
return 0;
}
Now, how do you get it allocated without changing the scope of this variable a?
I am sure there a lot of ways to solve your problem. Here's my suggestion.
Change the definition of struct foo to contain a fixed number of characters in s.
Create a as an object instead of a pointer. Initialize it with the necessary values.
Make a a static variable so its use is limited to the file only.
Use the object a instead of the pointer a in rest of the file.
#include <stdio.h>
struct foo
{
char s[20];
int n;
};
static struct foo a = {"HELLO", 20};
int main()
{
puts("Dummy outputs!\n");
printf("%s\n",a.s);
printf("%d\n",a.n);
return 0;
}
This:
struct foo
{
char s[] = "HELLO";
int n = 5;
};
Is not valid C code. You first declare the type:
struct foo
{
char s[10];
int n;
};
Then define a variable of that type:
static struct foo a = { "HELLO", 5 };
The static keyword allows this variable to have file local scope.
You can now use it like this:
static struct foo a = { "HELLO", 5 };
void other()
{
puts("Dummy outputs!\n");
printf("%s\n",a.s);
printf("%d\n",a.n);
}
int main()
{
puts("Dummy outputs!\n");
printf("%s\n",a.s);
printf("%d\n",a.n);
other();
return 0;
}
Note that a is accessible from both functions. It will not however be viewable from functions defined in other files because it is declared as static.
As for using a pointer vs the struct directly, you can take the address of this structure at any time you need to use it in that way:
some_function(&a);
well, i need to use a pointer instead of a structure directly
Try this:
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
struct foo{
char s[20];
int n;
};
int main(void){
struct foo *a;
a = malloc(sizeof(struct foo));
puts("Dummy outputs!\n");
strcpy(a->s, "HELLO");
a->n = 5;
printf("%s\n",a->s);
printf("%d\n",a->n);
free(a);
return 0;
}
Output:
Dummy outputs!
HELLO
5

How to typecast void pointer based on condition?

To explain more, I have two structures-'first' and 'second' having common variables 'jack' and 'jill'. I want to print jack via a pointer based on if-else condition.
I understand at the time of printing I have to typecast the void pointer. But whether the pointer points to struct a or b is decided on run time.
It is a basic C code. How to overcome this?
Code
#include <stdio.h>
int main(void)
{
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
a first;
b second;
void *z;
if(1)
{
a* z;
z = &first;
printf("First one");
}
else
{
b* z;
z = &second;
printf("Second one");
}
printf("%d\n", z->jack);
return 0;
}
Error
prog.c:36:17: warning: dereferencing 'void *' pointer printf("%d\n", z->jack); prog.c:36:17: error: request for member 'jack' in something not a structure or union
You get a compiler warning since the compiler does not understand z->jack since z is a void * (note that the declarations a* z and b* z are not valid outside the scope of the if and else block).
To overcome this you can use a function printJack as shown in the following listing:
#include <stdio.h>
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
void printJack(void *pStruct, int type)
{
switch (type)
{
case 1:
printf("jack: %d\n", ((a *)pStruct)->jack);
break;
default:
printf("jack: %d\n", ((b *)pStruct)->jack);
break;
}
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.jack = 5;
second.jack = 4892;
printJack(&first, 1);
printJack(&second, 0);
z = &first;
printJack(z, 1);
return (0);
}
I've written code like this often and experienced a lot of trouble with it. Not at the time of implementing, since you are knowing what you are typing at that moment but let's say a few years later if you need to extend your code. You will miss a few places where you cast from void * to a * or b * and you'll spend a lot of time debugging what's going on...
Now I'm writing things like this in the following way:
#include <stdio.h>
typedef struct header
{
int jack;
float jill;
} h;
typedef struct one
{
struct header header;
/* what ever you like */
}a;
typedef struct two
{
struct header header;
char something;
int something1;
/* and even more... */
}b;
void printJack(void *pStruct)
{
printf("jack: %d\n", ((struct header *)pStruct)->jack);
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.header.jack = 5;
second.header.jack = 4892;
printJack(&first);
printJack(&second);
v = &first;
printJack(v);
return (0);
}
As you've noticed I have declared a new struct header which covers the the common parts of struct one and struct two. Instead of casting the void * to either a * or b * a "common" cast to struct header * (or h *) is done.
By doing so you can easily extend the "common attribtues" of the structs or you can implement further structs using this header and function printJack still will work. Additionally there is no need for attribute type anymore making is easier to call printJack. You can even change the type of jack without needing to change it in various places within your code.
But remember that struct header needs to be the first element of the structs you use this mechanism. Otherwise you will end up with a few surprises since you are using memory which does not contain the data of the struct header...

Assigning values and passing struct as parameter

To asign a char value into the struct 'field', I have to use strcpy ?
I tried this:
struct student{
char name[50];
int age;
};
int main(){
struct student std;
std.name = "john"; //Doesnt work
strcpy(std.name, "john"); //It DOES work
std.age = 20;
return 0;}
Why when comes to char I can not simply use the ' = ' to assign a value ?
How may I pass a struct initialized in main(){} as a parameter to a function and change it's values inside the function without the need of a return.
Do I just use the '*' like:
void MyFunction(struct student *std){
std->Name = "John";
std->Age = 20;
}
int main(){
struct student me;
Myfunction(me);
}
Is that the correct way to do so ?
No matter which way you pass the struct (by value or by pointer), you cannot directly assign a string literal to a char array. You can only use strcpy or strncpy or something else that copies the characters one by one.
But there is a workaround, you can directly assign struct to another one. C compiler will perform a bitwise copy of the struct.
struct student s1;
strcpy(s1.name, "john");
s1.age = 10;
struct student s2;
s2 = s1; // now s2 is exactly same as s1.
Attach an example of use pointer to pass struct:
void handle_student(struct student *p) { ... }
int main() {
struct student s1;
handle_student(&s1);
}
This is just an additional information
While declaring the structure variable, it can be initialized as below.
int main(){
struct student s1 = {"John", 21};
//or
struct student s = {.name= "John" };
}

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

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;
}

Initializing a Struct of a Struct

If I have a struct in C that has an integer and an array, how do I initialize the integer to 0 and the first element of the array to 0, if the struct is a member another struct so that for every instance of the other struct the integer and the array has those initialized values?
Initialisers can be nested for nested structs, e.g.
typedef struct {
int j;
} Foo;
typedef struct {
int i;
Foo f;
} Bar;
Bar b = { 0, { 0 } };
I hope this sample program helps....
#include <stdio.h>
typedef struct
{
int a;
int b[10];
}xx;
typedef struct
{
xx x1;
char b;
}yy;
int main()
{
yy zz = {{0, {1,2,3}}, 'A'};
printf("\n %d %d %d %c\n", zz.x1.a, zz.x1.b[0], zz.x1.b[1], zz.b);
return 0;
}
yy zz = {{0, {0}}, 'A'}; will initialize all the elements of array b[10] will be set to 0.
Like #unwind suggestion, In C all instances created should initialized manually. No constructor kind of mechanism here.
You can 0-initialize the whole struct with {0}.
For example:
typedef struct {
char myStr[5];
} Foo;
typedef struct {
Foo f;
} Bar;
Bar b = {0}; // this line initializes all members of b to 0, including all characters in myStr.
C doesn't have constructors, so unless you are using an initializer expression in every case, i.e. write something like
my_big_struct = { { 0, 0 } };
to initialize the inner structure, you're going to have to add a function and make sure it's called in all cases where the structure is "instantiated":
my_big_struct a;
init_inner_struct(&a.inner_struct);
Here is an alternative example how you would do things like this with object-oriented design. Please note that this example uses runtime initialization.
mystruct.h
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct mystruct_t mystruct_t; // "opaque" type
const mystruct_t* mystruct_construct (void);
void mystruct_print (const mystruct_t* my);
void mystruct_destruct (const mystruct_t* my);
#endif
mystruct.c
#include "mystruct.h"
#include <stdlib.h>
#include <stdio.h>
struct mystruct_t // implementation of opaque type
{
int x; // private variable
int y; // private variable
};
const mystruct_t* mystruct_construct (void)
{
mystruct_t* my = malloc(sizeof(mystruct_t));
if(my == NULL)
{
; // error handling needs to be implemented
}
my->x = 1;
my->y = 2;
return my;
}
void mystruct_print (const mystruct_t* my)
{
printf("%d %d\n", my->x, my->y);
}
void mystruct_destruct (const mystruct_t* my)
{
free( (void*)my );
}
main.c
int main (void)
{
const mystruct_t* x = mystruct_construct();
mystruct_print(x);
mystruct_destruct(x);
return 0;
}
You don't necessarily need to use malloc, you can use a private, statically allocated memory pool as well.

Resources