Pointing to an array inside a struct that is inside another struct - c

How can I access an array / other type of data that is inside of a struct which is inside of another struct. This is what Ive tried so far and its coming out as c is not declared. I know I can declare c as prod_t *c but it defeats the purpose of something Im trying to do as it doesnt exist inside of the root(a_t struc).
typedef struct {
char *name;
} prod_t;
typedef struct {
prod_t *c;
} a_t;
int
main(int agrc, char **argv){
a_t *root = malloc(sizeof(a_t));
root->c=malloc(sizeof(prod_t));
c->name = malloc( 5 * sizeof(char));
strcpy(c->name, "abc");
printf("%s",root.c->name);
return 0;
}

In your code, c->name is not a valid variable name. c is a member variable of the structure variable root. There is no standalone variable named c.
You can use like
root->c->name = malloc( 5 );
and
strcpy(root->c->name, "abc");
and
printf("%s\n", root->c->name);
Also, remember,
sizeof(char) is guranteed to produce 1 in C, so you can drop that part.
Once you're done using the allocated memory, you need to free() them.

You have three pointers one is "enclosed" in another. So you have to write
root->c->name = malloc( 5 * sizeof(char));
strcpy( root->c->name, "abc");
printf("%s",root->c->name);
And you have to free them in the following order
free( root->c->name );
free( root->c );
free( root );
Take into account that in general you have to check whether the "outer" pointer was successfully "allocated" before allocating memory pointed to by the "inner" pointer.

Related

Can I iterate dynamic array without knowing the size of it

I allocated some data in a dynamic array of a struct. Can I iterate that struct * without knowing it's size somehow?
Would this work?
int main() {
struct *foo = NULL;
//struct filling
iterate_foo(foo);
}
void iterate_foo(struct *foo) {
int i=0;
while (foo[i] != NULL) { // Would this work?
//something
}
}
The only way that can work is if you have a sentinel value in the array that indicates the end. Strings in C work that way.
For instance, if you invoke strcpy(a, b), then characters from b will be copied to a until and including the value zero. If there's no zero terminator within the b array, or if a is not big enough to hold all the characters, the function call leads to undefined behavior.
If you don't want to use a sentinel value, you have the option of passing the size as a separate parameter. Another way is to wrap things in a container struct, like this:
struct container {
struct mystruct *data;
size_t size;
}
Furthermore, struct *foo = NULL; is wrong. It has to be something like struct mystruct *foo = NULL;
But if you have this code:
void foo(T *ptr) {
// Do something
}
int main(void) {
T *a = malloc(N * sizeof *a);
T b[N];
foo(a);
foo(b);
}
Then it's completely impossible for foo to figure out N in a portable way. In some cases, believe that the implementation of malloc stores the size right before the data. But don't try to exploit that. It will only cause severe head ache.

Can I use malloc when defining a structure?

Is there any way to dynamically allocate memory for a structure in the definition of the structure, and if it can't be done, what is the best way to dynamically allocate memory for that structure ?
typedef struct user_t{
char user_name[30];
char email[50];
int movieswatched;
movie *movielist;
}user_t;
I want to allocate memory for movielist .
You can use a flexible array member:
typedef struct user_t{
char user_name[30];
char email[50];
int movieswatched;
movie movielist[]; // The flexible array member,
// must always be last and declared as an array without a size
}user_t;
A structure like this must be allocated dynamically (with e.g. malloc), for example as
user_t *my_user = malloc(sizeof *my_user + sizeof(movie) * 50); // Allocate space for 50 movies
You can't do it in the definition of the structure (which wouldn't make much sense anyway as you don't yet know the number of movies and because different user_t variables might have different number of movies).
You need to do it at runtime, for example like this:
user_t v;
...
v.movielist = malloc(sizeof(movie) * numberofmovies);
You could define a 'factory' function. That's a fancy name for a function that does both mallocs for you. Something like :
user_t *user_factory( const int movies_watched )
{
user_t *user = malloc(sizeof *my_user); // should check for NULL
user->movieswatched = movies_watched;
user->movielist = malloc(sizeof(movie) * movies_watched);
return user;
}
It's common to combine the mallocs, BTW, then you can use #someprogrammerdude's flexible array member approach (but still wrap it in the factory). The other advantage of their way is that it's harder to have an accidental memory leak.
If you really want an automatic variable as you have in your example, then you can have a half-way house of init (and deinit) functions:
void init_user_t( user_t *user, const int movies_watched )
{
user->movieswatched = movies_watched;
user->movielist = malloc(sizeof(movie) * movies_watched);
}
void deinit_user_t( user_t *user )
{
free( user->movielist );
user->movielist = NULL;
user->movieswatched = 0;
}
...
user_t my_user;
init_user_t( &my_user, 6 /*num_movies*/ );

Accessing dynamic memory in a struct pointer

I'm writing some code to interact with dynamic memory that i' creating and i want to know why it's not working.
struct order{
char *bookTitle;
double price;
char *category;
double remain;
int custID;
char processed;
};
typedef struct order order;
struct orderNode{
order *order;
struct orderNode *next;
};
typedef struct orderNode orderNode;
Here is the code creatinng an array or orderNodes and trying to access them. The print statement is giving me a segmentation fault. Not sure why.
orderNode **processQueue = malloc(sizeof(orderNode)*numcats) ;
//sort the orders into their respective categories
//sortOrders(processQueue, unSortedQueue, numcats);
processQueue[1]->order->category = "herro" ;
puts("string set. \n");
printf("%s\n",processQueue[1]->order->category);
/*
gdb backtrace output.
#0 strlen () at ../sysdeps/x86_64/strlen.S:106
#1 0x00007ffff786794c in _IO_puts (str=0x1000000000a2074 <error: Cannot access memory at address 0x1000000000a2074>)
at ioputs.c:36
#2 0x000000000040192f in main (argc=4, argv=0x7fffffffdbd8) at main.c:444
*/
Thanks in advance!
I think that instead of
orderNode **processQueue = malloc(sizeof(orderNode)*numcats) ;
you mean
orderNode *processQueue = malloc(sizeof(orderNode)*numcats) ;
Also take into account that for each orderNode in the array you have to allocate data member order before trying to access its own data members.
And indices in C start from zero. It seems that in this statement
processQueue[1]->order->category = "herro" ;
you want to access processQueue[0] instead of processQueue[1]
The code could look like
orderNode *processQueue = malloc( sizeof( orderNode ) * numcats );
processQueue[0].order = malloc( sizeof( order ) );
processQueue[0].order->category = "herro";
puts( "string set." );
puts( processQueue[0].order->category );
You never allocated any of your order:
orderNode *processQueue = calloc(numcats, sizeof(orderNode)) ;
for (i=0;i<numcats;i++)
processQueue[i].order = calloc(1, sizeof(order));
Also, I used calloc for the first allocation to make sure all of your next pointers are NULL. I'm not sure what you plan on doing with those next pointers, though.
EDIT: also, as Vlad from Moscow pointed out, processQueue was of the wrong type (I fixed the type above).

display a specified index of a pointer char*

I am trying to point on a specified character in a string contained on a structure
here my code
typedef struct{
char *name;
int age;
}PERSON, *person;
int main(){
person serenity;
serenity = (person)malloc(sizeof(PERSON));
strcpy(&(serenity->name),"Serenity");
printf("%c",*(&(serenity->name)+1));
}
here i wanted to display the second character which is 'e' but it shows 'n' instead
anyone can explain me what is wrong with this,
thank you
You have not allocated memory for name
typedef struct{
char *name;
int age;
}PERSON, *person;
int main(){
person serenity;
serenity = malloc(sizeof(PERSON));
serenity->name = malloc(sizeof("Serenity")); //<< Missing
strcpy((serenity->name),"Serenity");
printf("%c",*((serenity->name)+1)); // << Also you want the value in pointer name NOT its address
return 0;
}
Outputs e. Also since you tagged C there is no need to cast the return type of malloc.
Okay, okay... All of those answers aside, if you do not aim to change the characters inside the string "Serenity" in the future, you could just do the following:
#include <stdio.h>
typedef struct{
const char *name; // <-- added const
int age;
}PERSON, *person;
int main( ){
person serenity;
serenity = (person) malloc( sizeof( PERSON ) );
serenity->name = "Serenity"; // <-- simply assigned the pointer with the
// address to the array of constant characters
printf( "%c", *( serenity->name + 1 ) ); // <-- changed this
}
This statement
serenity = (person)malloc(sizeof(PERSON));
allocates the structure
typedef struct{
char *name;
int age;
}PERSON
however name is kept uninitialized and points somewhere in memory causing a crash when you copy to it.
So instead of
strcpy(&(serenity->name),"Serenity");
write
serenity->name = strdup("Serenity");
which is the same as
serenity->name = malloc(strlen("Serenity")+1);
strcpy(serenity->name,"Serenity");
don't forget to free that string as well later.
Try printf("%c",*(serenity->name+1));, also do strcpy(serenity->name,"Serenity");.
If you have a pointer char* name; you access the second element by doing name[1] or *(name+1). &name will give you the address where the pointer address of name is stored. This is not what you want here.
Another issue in your program is that you never allocate memory for the variable name. You need a serenity->name = (char*)malloc(128);. But using an arbitrary length like 128 is very dangerous in combination with strcpy. Use strncpy instead of strcpy to work around this.

How to access union inside structure?

I have the following code:
/* sample.c */
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include"hermes.h"
#include<string.h>
int main (){
struct hermes *h ;
h = ( struct hermes *) malloc ( sizeof ( struct hermes *));
strcpy ( h->api->search_response->result_code , "123" );
printf("VALue : %s\n" , h->api->search_response->result_code );
return 0;
}
/* hermes.h */
struct hermes {
union {
/* search response */
struct {
int error_code;
char *result_code;
char *user_track_id;
struct bus_details bd;
}*search_response;
}*api;
};
I get a segmentation fault when I try to access the elements. Could anyone tell me what is the right way to access these elements?
Your malloc() line isn't correct:
h = ( struct hermes *) malloc ( sizeof ( struct hermes *));
should be:
h = ( struct hermes *) malloc ( sizeof ( struct hermes));
Remove the * in the sizeof(). Otherwise, you're only allocating enough for a pointer rather than the struct itself.
Also, the cast isn't necessary in C.
Use this struct:
#define MAX 512 /* any number you want*/
struct hermes {
union {
/* search response */
struct {
int error_code;
char result_code[MAX];
char user_track_id[MAX];/* can use different sizes too*/
struct bus_details bd;
}search_response[MAX];/* can use different sizes too*/
}*api;
};
Or if you want to use your current struct, malloc the pointer element like:
h->api = malloc((sizeof(int)+sizeof(char)*MAX*2+sizeof(struct bus_details))*MAX)
It's not a problem of accessing the elements. That's about all that you are doing correctly.
Here are some of the things that are wrong. First, you aren't allocating enough space for a hermes struct, just enough for a pointer. Then, even if you malloc( sizeof ( struct hermes ) );, the one element (api) is an uninitialized pointer. You can't just follow uninitialized pointers down deep into the data structure, because they will be pointing to who knows where in memory. You first need to allocate something for h->api to point to. Then you need to allocate space for h->api->search_response. If you correct all that, then you are copying a string to ... who knows where? You should use strdup, not strcpy to create a new string, then you should assign the return value to result_code. Also, your union has only one element, so it's kind of pointless (unless there's more to it that you haven't posted).
EDIT Here's one way of initializing h:
h = malloc( sizeof( struct hermes ) );
h->api = malloc( sizeof( *h->api ) );
h->api->search_response = malloc( sizeof( h->api->search_response ) );
h->api->search_response->result_code = strdup( "123" );
Note that in a well-behaved program that cleans up after itself, each of these allocations will have to be freed individually as well, in reverse order of the calls to malloc. Since you immediately call exit(0), no harm is done in this case if you don't.

Resources