Accessing pointer member variable of the innermost of three nested structs - c

typedef struct {
struct {
double i1, i2;
} EXP;
struct {
double i1, i2;
} SIN;
struct {
double i1, i2;
} PULSE;
struct {
double *i1, *i2;
} PWL;
} TRANS;
struct term {
TRANS trans;
struct term *nxt;
};
int main() {
struct term *look;
}
I have the above structs and the pointer look to the struct term. Could someone tell me how to dereference pointer i1 inside struct PWL?
I've tried this:
*(look->trans.PWL.i1)
but it produces segmentation fault.
Thanks in advance!

The segmentation fault is because you allocated a pointer, but did not create memory for the pointer to point at. Once you do that, then *(look->trans.PWL.i1) is indeed how to access that field in the inner struct.
You need to allocate memory for the struct, and all references within.
struct term *look = malloc(sizeof(struct term));
look->trans.PWL.i1 = malloc(sizeof(double));
look->trans.PWL.i2 = malloc(sizeof(double));
And naturally you need to reverse the process with calls to free when you are done.
free(look->trans.PWL.i2);
free(look->trans.PWL.i1);
free(look);
Or, perhaps i1 and i2 are meant to point to values that are allocated elsewhere then it would look like this:
struct term *look = malloc(sizeof(struct term));
look->trans.PWL.i1 = &look->trans.EXP.i1;
look->trans.PWL.i2 = &look->trans.EXP.i2;
And to deallocate you just free look. Remember to pair each successful call to malloc with a call to free.

Specific to PWL.i1
int main() {
struct term *look; // set up your variable
look = malloc(sizeof(struct term)); // give it some memory
look->trans.PWL.i1 = malloc(sizeof(double)); //give some memory to your double pointer
*(look->trans.PWL.i1) = 5.0; // assign it a value
printf("%lf\n", *(look->trans.PWL.i1));
return 0;
}
So since look is a pointer to a term structure, that means when you access it's elements you need to deference it then access the members (->) once you have that you just access the other members via the . operator:
look->trans.PWL.i1
In this case PWL's i1 member is a pointer so you have to deference the whole thing to assign a value. (before doing so, again you need to allocate some memory there)
And free everything when you're done of course.

Related

Segmentation Fault while trying to fill a list [duplicate]

Suppose I have the following struct and function returning a pointer:
typedef struct {
int num;
void *nums;
int size;
} Mystruct;
Mystruct *mystruct(int num, int size)
{
//Is the following correct? Is there a more efficient way?
Mystruct mystruct;
mystruct.num = num;
mystruct.size = size;
mystruct.nums = malloc(num*sizeof(size));
Mystruct *my;
*my = mystruct;
return my;
}
I want to define any Mystruct pointer using the above function. Should I declare a Mystruct variable, define the properties of Mystruct, assign a pointer to it, and return the pointer or define the properties of a mystruct property through a pointer immediately?
Should I declare a Mystruct variable,
define the properties of Mystruct,
assign a pointer to it, and return the
pointer
Definitely not, because the variable defined in the function (in "auto" storage class) will disappear as the function exits, and you'll return a dangling pointer.
You could accept a pointer to a Mystruct (caller's responsibility to allocate that) and fill it in; or, you can use malloc to create a new one (caller's responsibility to free it when it's done). The second option at least lets you keep the function signature you seem to be keen on:
Mystruct *mystruct(int num, int size)
{
Mystruct *p = malloc(sizeof(MyStruct));
....
return p;
}
but it's often an inferior one -- since the caller has to have responsibilities anyway, may as well go with the first option and potentially gain performance (if the caller can use an auto-class instance because it knows the scope of use is bounded).
You can't use the variable because it will be deallocated when the function exits. For example:
Mystruct *mystruct(int num, int size)
{
MyStruct x;
x.num = 1;
...
return &x;
}
Will give a segmentation fault or access violation because the memory for x is deallocated as soon as you exit. So you have to allocate memory for the struct (and be sure to free it up later) or declare a global that will stay around for ever. Example for the latter...
Mystruct *mystruct(int num, int size)
{
MyStruct *x;
x = (MyStruct*)malloc( sizeof( MyStruct ) );
x->num = 1;
...
return x;
}
If you are writing generic code and you don't know how it may be used, it's good to provide both options:
int mystructm(Mystruct *storage, int num, int size)
{
int rv = 0;
storage->num = num;
storage->size = size;
storage->nums = malloc(num*sizeof(size));
if (!storage->nums)
return -1;
return 0;
}
Mystruct *mystruct(int num, int size)
{
Mystruct *mp = (Mystruct *)malloc(sizeof(Mystruct));
if (mp)
{
if (mystructm(mp, num, size) == -1)
{
free(mp);
mp = NULL;
}
}
return mp;
}
The idea is that as a library writer, you shouldn't dictate policy (such as that each Mystruct must be dynamically allocated) but should let the application writer decide that.
It's important to remember that the pointer is not something you assign to the structure, but rather the pointer indicates the location in memory that you wish to treat as a structure. Based on your question, you really want to allocate the memory to hold the data structure. This gives you a pointer to the memory location allocated. Once you have that, you can return it.
EDIT (after edit to original question)
Looking at your edit to the question, you definitely will have problems with the "my" pointer. This is uninitialised, and may point to anywhere in memory. When you attempt to copy the structure to it, you'll probably get a seg-fault.
Allocating a new Mystruct and returning a pointer to it would usually look more or less like this:
Mystruct *mystruct(int num, int size)
{
Mystruct *result;
result = malloc(sizeof(MyStruct));
if (!result)
return NULL;
result->num = num;
...
return result;
}
Later, when you are done with the Mystruct allocated here with malloc, it should be freed again with free().
Just declaring a local variable and returning a pointer to that local variable will not work. The local variable goes out of scope at the end of the function and the memory where it was stored is most likely reused for other purposes. The returned pointer will still point to the memory location where the local variable once was, but since that variable doesn't exist anymore, that pointer wouldn't be of much use.
One more way to do it..
int mystruct(Mystruct *mystruct, int num, int size){
if(mystruct == NULL)
return -1;
mystruct->num = num;
mystruct->size = size;
::
return 0;
}
int main(){
Mystruct my;
if(mystruct(&my, 3, 4) != 0){
fprintf(stderr, "Cannot init!\n");
exit(0);
}
::
}

Pointers to structs and printing

I've been learning structs and I've come to the pointers to structs, where I'm currently struggling with this.
I've got this piece of code:
struct point {
int x;
int y;
} *ptr;
ptr->x = 8;
ptr->y = 8;
Running this gives a segmentation error. What I want to do is assign the value of 8 to x /y, to which, as far as I understand it, ptr is pointing to.
Your ptr is a pointer to struct point.
However, there is no struct point it is pointing to.
struct point {
int x;
int y;
} *ptr;
struct point pt; // add this...
ptr = &pt; // ...and this.
ptr->x = 8;
ptr->y = 8;
You have created a pointer called ptr but not initialized it. When you dereference it with ptr-> (or *ptr), you invoke undefined behavior which in your case is crashing the program (but could do anything).
This would be better:
struct point {
int x;
int y;
};
struct point sp = {0,0};
struct point *ptr = &sp;
sp.x = 8;
ptr->y = 8;
The problem is that the pointer ptr does not point to any valid memory buffer, assign it to a allocated or automatic storage instead:
// way 1
struct point p;
ptr = &p;
ptr->x = 8;
ptr->y = 8;
// way 2
ptr = malloc(sizeof *ptr);
ptr->x = 8;
ptr->y = 8;
// when you are done remember to release the allocated memory
free(ptr);
Let me explain you the simple way.
1.
Variables hold the data(values to want them to hold) and pointers hold only the memory address of the variables(which are just a section of memory). Pointers are used to just hold the address of the variables so they cannot hold any user data. We can although create a pointer to a variable and manipulate that variable using the specific pointer. We first need to create the variable, then we create a pointer which references that variable, then we do anything with the pointer and the variable will be manipulated.
struct point
{
int x;
int y;
};
struct point var1; //declare a variable
struct point *ptr=&var1;// declare a pointer to that variable
ptr->x = 8; // manipulate the variable
ptr->y = 8;
Or
2.
If you insist on using pointers only, then you need to allocate memory dynamically and then assign the base address of the allocated memory to the pointer.
struct point
{
int x;
int y;
} *ptr;
ptr=(struct point*)malloc(sizeof(struct point)); // this will allocate memory required to hold your structure
ptr->x = 8; //manipulate the memory content pointed by your pointer.
ptr->y = 8;
You need to assign a valid memory location to ptr, which is a pointer to struct point. You could either use malloc, or declare a variable with struct point and assign its address to ptr (like the above answers).
Btw, if ptr has file scope, then it is initialized with zero, i.e., the NULL pointer; otherwise, evaluating ptr is undefined behavior (you could get any value). In both cases, trying to dereference ptr is undefined behavior and thus you could get the segfault (in some implementation you might modified some memory location unintendedly).

Is it possible to return a pointer to a struct without using malloc?

I'm writing a Gameboy ROM using the GBDK, which has an unstable version of malloc that I'm unable to get working. I'm also unable to return a struct within a struct. That leaves me trying to return a pointer, which is why I'm wondering if there is a way to avoid using malloc when returning a struct pointer?
What I'm basically trying to do is that I want to be able to write something like this:
create_struct(struct_name, char member_x, char member_y);
This is the code I have written using malloc:
struct point {
char member_x;
char member_y;
};
struct point *makepoint(char member_x, char member_y) {
struct point *temp = malloc(sizeof(struct point));
temp->member_x = member_x;
temp->member_y = member_y;
return temp;
};
There are various valid ways to return a pointer (to a struct, or any type of object), but the only way to return a pointer to a new object that didn't exist before the function was called is to use malloc, realloc, calloc, aligned_alloc (C11), or some implementation-defined allocation function (e.g. mmap on POSIX systems, etc.).
Other ways you could return a valid pointer include:
A pointer to an object with static storage duration. Only once instance of such an object exists, so this is usually a bad way.
A pointer that was passed to the function as an argument for use as a place to store the result. This can often be a good approach, since you pass off responsibility for obtaining the storage to the caller.
A pointer to an object obtained from some sort of global pool. This could be a very good approach in embedded systems and game design for low-end gaming devices.
Is it possible to return a pointer to a struct without using malloc?
I. Technically, yes. You can make your struct static so that it survives function calls:
struct foo *bar()
{
static struct foo f = { 1, 2, 3 };
return &f;
}
But I doubt you actually want to do this (since this has funny side effects, read up on the meaning of the static keyword). You have several different possibilities:
II. The approach what the C standard library takes is always making the caller implicitly responsible for providing the struct and managing memory. So instead of returning a pointer, the function accepts a pointer to struct and fills it:
void dostuff(struct foo *f)
{
foo->quirk = 42;
}
III. Or return the struct itself, it doesn't hurt, does it (it can even be move-optimized):
struct foo bar()
{
struct foo f = { 1, 2, 3 };
return f;
}
So, choose your poison.
just do something like:
void makepoint(struct point *dest, char member_x, char member_y) {
dest->member_x = member_x; // you had these wrong in your code, by the way
dest->member_y = member_y;
}
The structure will need to be "allocated" elsewhere (probably on the stack is your best bet).
You could pass the struct as a parameter and have the function initialize it :
struct point *makepoint(struct point *pt, char x, char y) {
pt->x = x;
pt->y = y;
return pt;
}
and then call it like this :
struct point pt;
makepoint(&pt, 'a', 'b');
but then you might as well just have done :
struct point pt = { 'a', 'b' };
Note that in this case (struct point only occupies 2 bytes) you can return struct point instead of struct point *, (this should not be done with large structs)
#include <stdio.h>
struct point {
char member_x;
char member_y;
};
struct point makepoint(char member_x, char member_y)
{
struct point temp;
temp.member_x = member_x;
temp.member_y = member_y;
return temp;
}
int main(void)
{
struct point t = makepoint('a', 'b');
printf("%c %c\n", t.member_x, t.member_y);
return 0;
}
If it is not possible to get malloc() fixed, then you may just want to manage your own pre-allocated points, and limit the number of points that can be "created". You would need to alter your points a little to allow for easier management:
union free_point {
union free_point *next;
struct point data;
};
union free_point free_point_pool[MAX_POINTS];
union free_point *free_point_list;
struct point *makepoint(char member_x, char member_y) {
static int i;
union free_point *temp;
temp = 0;
if (i == MAX_POINTS) {
if (free_point_list) {
temp = free_point_list;
free_point_list = temp->next;
}
} else {
temp = free_point_pool + i++;
}
if (temp) {
temp->data.x = x;
temp->data.y = y;
}
return &temp->data;
};
Then, instead of calling free() on the result returned by makepoint(), you should create a new function to place it on the free_point_list.
void unmakepoint (struct point *p) {
union free_point *fp = (union free_point *)p;
if (fp) {
fp->next = free_point_list;
free_point_list = fp;
}
}
The simplest thing is just to return a structure that has been created using named initializers, and do so in an inline function, so that there is zero overhead:
static inline struct point makepoint(char x, char y) {
return (struct point) { .x = x, .y = y };
}
Then you can call it like this:
struct point foo = makepoint(10, 20);
Couldn't be simpler!

ansi-c - assign array value in structure

I need help assigning a value to an array with in a structure. Your help is greatly appreciated:
typedef struct _temp_t {
int16_t _values[4];
} TEMP_T;
void func() {
TEMP_T *temps;
int x = 5;
temps._values[0] = x;
}
I'm getting an error :
...src/rodm/ucdCom.c:512: error: request for member '_values' in something not a structure or union
Your help is greatly appreciated!
TEMP_T *temps;
temps is a pointer, so it has no members, only structs and unions have members.
After you allocated memory for temps, you could set
temps->_values[0] = x;
Or you can declare temps as a TEMP_T,
TEMP_T temps;
and leave the rest of the code as is.
TEMP_T *temps;
Drop the * from that line. Then it will be a true TEMP_T object instead of a pointer.
Alternatively, malloc some memory to temps and then use:
temps->_values[0] = x;
The OP didn't have any sign of an allocated struct TEMPT_T anywhere.
He had a pointer, but nothing for it to point to. His code then attempts an assignment with member access syntax (temps._values[0];), as opposed to pointer access syntax (temps->_values[0];).
A slightly better version of his code might look like:
typedef struct _temp_t {
int16_t _values[4];
} TEMP_T;
void func(struct TEMPT_T in) {
TEMP_T *temps = &in;
int x = 5;
temps->_values[0] = x;
}
The function's new definition implies that a struct TEMP_T must exist for it to be used, and thus the pointer access into the structure becomes legal.

Returning a struct pointer

Suppose I have the following struct and function returning a pointer:
typedef struct {
int num;
void *nums;
int size;
} Mystruct;
Mystruct *mystruct(int num, int size)
{
//Is the following correct? Is there a more efficient way?
Mystruct mystruct;
mystruct.num = num;
mystruct.size = size;
mystruct.nums = malloc(num*sizeof(size));
Mystruct *my;
*my = mystruct;
return my;
}
I want to define any Mystruct pointer using the above function. Should I declare a Mystruct variable, define the properties of Mystruct, assign a pointer to it, and return the pointer or define the properties of a mystruct property through a pointer immediately?
Should I declare a Mystruct variable,
define the properties of Mystruct,
assign a pointer to it, and return the
pointer
Definitely not, because the variable defined in the function (in "auto" storage class) will disappear as the function exits, and you'll return a dangling pointer.
You could accept a pointer to a Mystruct (caller's responsibility to allocate that) and fill it in; or, you can use malloc to create a new one (caller's responsibility to free it when it's done). The second option at least lets you keep the function signature you seem to be keen on:
Mystruct *mystruct(int num, int size)
{
Mystruct *p = malloc(sizeof(MyStruct));
....
return p;
}
but it's often an inferior one -- since the caller has to have responsibilities anyway, may as well go with the first option and potentially gain performance (if the caller can use an auto-class instance because it knows the scope of use is bounded).
You can't use the variable because it will be deallocated when the function exits. For example:
Mystruct *mystruct(int num, int size)
{
MyStruct x;
x.num = 1;
...
return &x;
}
Will give a segmentation fault or access violation because the memory for x is deallocated as soon as you exit. So you have to allocate memory for the struct (and be sure to free it up later) or declare a global that will stay around for ever. Example for the latter...
Mystruct *mystruct(int num, int size)
{
MyStruct *x;
x = (MyStruct*)malloc( sizeof( MyStruct ) );
x->num = 1;
...
return x;
}
If you are writing generic code and you don't know how it may be used, it's good to provide both options:
int mystructm(Mystruct *storage, int num, int size)
{
int rv = 0;
storage->num = num;
storage->size = size;
storage->nums = malloc(num*sizeof(size));
if (!storage->nums)
return -1;
return 0;
}
Mystruct *mystruct(int num, int size)
{
Mystruct *mp = (Mystruct *)malloc(sizeof(Mystruct));
if (mp)
{
if (mystructm(mp, num, size) == -1)
{
free(mp);
mp = NULL;
}
}
return mp;
}
The idea is that as a library writer, you shouldn't dictate policy (such as that each Mystruct must be dynamically allocated) but should let the application writer decide that.
It's important to remember that the pointer is not something you assign to the structure, but rather the pointer indicates the location in memory that you wish to treat as a structure. Based on your question, you really want to allocate the memory to hold the data structure. This gives you a pointer to the memory location allocated. Once you have that, you can return it.
EDIT (after edit to original question)
Looking at your edit to the question, you definitely will have problems with the "my" pointer. This is uninitialised, and may point to anywhere in memory. When you attempt to copy the structure to it, you'll probably get a seg-fault.
Allocating a new Mystruct and returning a pointer to it would usually look more or less like this:
Mystruct *mystruct(int num, int size)
{
Mystruct *result;
result = malloc(sizeof(MyStruct));
if (!result)
return NULL;
result->num = num;
...
return result;
}
Later, when you are done with the Mystruct allocated here with malloc, it should be freed again with free().
Just declaring a local variable and returning a pointer to that local variable will not work. The local variable goes out of scope at the end of the function and the memory where it was stored is most likely reused for other purposes. The returned pointer will still point to the memory location where the local variable once was, but since that variable doesn't exist anymore, that pointer wouldn't be of much use.
One more way to do it..
int mystruct(Mystruct *mystruct, int num, int size){
if(mystruct == NULL)
return -1;
mystruct->num = num;
mystruct->size = size;
::
return 0;
}
int main(){
Mystruct my;
if(mystruct(&my, 3, 4) != 0){
fprintf(stderr, "Cannot init!\n");
exit(0);
}
::
}

Resources