C: Accessing pointer to pointer to struct element from pointer to structure - c

I want to access members of a struct from double pointer but I get the error
"error: expected identifier before ‘(’ token"
C Double Pointer to Structure
double pointer to struct inside struct
:
struct test{
struct foo **val;
};
struct foo{
int a;
}
int main (){
struct test *ptr = (struct test *)malloc(sizeof(struct test));
ptr->val = &foo;
/*foo is already malloced and populated*/
printf ("Value of a is %d", ptr->(*val)->a);
}
I've also tried:
*ptr.(**foo).a

You want to do this:
#include <stdio.h>
#include <stdlib.h>
struct test {
struct foo **val;
};
struct foo {
int a;
};
int main(void) {
struct test* test_ptr = malloc(sizeof(struct test));
struct foo* foo_ptr = malloc(sizeof(struct foo));
foo_ptr->a = 5; // equivalent to (*foo_ptr).a = 5;
test_ptr->val = &foo_ptr;
printf ("Value of a is %d\n", (*(test_ptr->val))->a);
free(test_ptr);
free(foo_ptr);
return 0;
}
Output:
C02QT2UBFVH6-lm:~ gsamaras$ gcc -Wall main.c
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
Value of a is 5
In my example:
I allocate dynamically space for a struct test.
I allocate dynamically space for a struct foo.
I assign the value 5 to the member a of foo_ptr.
I assign the address of the allocated object of struct foo to the
member val of test_ptr.
I print member a the struct that the double pointer val points
to.
Note, in your example: struct foo is a type, so it doesn't make sense to ask for its address.
Also, you were missing a semicolon when you were done with the declaration of struct foo.
Oh, and make sure not to cast the return value of malloc().

in ptr->val = &foo;, foo is a struct (you declared it in lines 5 to 7). Taking its address does not give a **, but only a *.
Also it seems multiple things have the same names; is a foo the name of a structure or an instance of it, or both?
Then, when you dereference it: ptr->(*val)->a does seem the wrong sequence.
as ptr->val is the address of foo (that's what you assigned in the line above it), what would ptr->(*val) be??
I think ptr->val.a would give you your a. But still, the val is declared as a ** and consistently used as a *. It might work, but makes not much sense.

Related

how to access a struct within a list within a struct with a pointer?

I'm given a number i, and a pointer which points to a struct which contains a list of structs, basically what I want to do is go over all of the lists and look which struct in it has the number i.
typedef struct struct1 { int num; } struct1;
typedef struct struct2 {
struct1 somestruct1;
struct2 *pnext;
} struct2;
struct struct3 {
struct2 somestruct2;
};
I'm new to coding and I can't seem to figure this out, here's how I'm trying to access a num field in some struct1 given a pointer to struct3
struct3 temp->somestruct2.somestruct1.num ;
It seems that your confusion might be due to whether to use a "." or a "->"
Here is a general rule...
If the item to the left is a pointer, use "->". If it is not a pointer, use ".".
If "temp" is defined "struct struct3 temp", then temp is not a pointer. Hence, it should be followed by a "." to access the sub-element(s) of temp.
The temp sub-element "somestruct1" is also not defined as a pointer in struct2; hence, to access the sub-element(s) of somestruct1, it should be followed by a ".".
temp.somestruct2.somestruct1.num
Here is an example of how that can be done.
#include <stdlib.h>
#include <stdio.h>
typedef struct struct1 { int num; } struct1;
typedef struct struct2 {
struct1 somestruct1;
struct struct2 *pnext;
} struct2;
struct struct3 {
struct2 somestruct2;
};
int main()
{
struct struct3* s = malloc(sizeof(struct struct3));
s->somestruct2.somestruct1.num = 1;
printf("%d\n", s->somestruct2.somestruct1.num);
free(s);
}
Whenever you have a pointer, you must dereference it before you can use the thing it points to. The dereference operator is unary * and then . to access the structs members.
So long hand you could write
(*s).somestruct2.somestruct1.num = 1;
This is a very common operation and its also quite ugly, so an operator that combines them is ->, hence
s->somestruct2.somestruct1.num = 1;
struct3 s3;
int num = s3.somestruct2.somestruct1.num;
or
struct3 *s3;
int num = s3->somestruct2.somestruct1.num;

Converting a pointer to a struct to its first member

Consider the following example program:
#include <stdio.h>
struct base {
int a, b;
};
struct embedded {
struct base base;
int c, d;
};
struct pointed {
struct base* base;
int c, d;
};
static void base_print(struct base* x) {
printf("a: %d, b: %d\n", x->a, x->b);
}
static void tobase_embedded(void* object) {
base_print(object); // no cast needed, suitably converted into first member.
}
static void tobase_pointed(void* object) {
struct base* x = *(struct base**) object; // need this cast?
base_print(x);
}
int main(void) {
struct embedded em = {{4, 2}};
struct pointed pt = {&em.base};
tobase_embedded(&em);
tobase_pointed(&pt);
return 0;
}
Compiled with:
$ gcc -std=c99 -O2 -Wall -Werror -pedantic -o main main.c
The expected output is:
$ ./main
a: 4, b: 2
a: 4, b: 2
The C99 standard says this about the first member of a structure:
C99 6.7.2.1 (13):
A pointer to a structure object, suitably converted, points to its initial member... and vice versa.
There may be unnamed padding within as structure object, but not at its beginning.
In the example program a pointer to struct embedded is converted to a pointer to struct base (through void*) without the need for an explicit cast.
What if instead the first member is a pointer to base as in struct pointed? I'm unsure about the cast within tobase_pointed. Without the cast garbage is printed, but no compilation warnings/errors. With the cast the correct values for base.a and base.b are printed, but that doesn't really mean much if there is undefined behavior.
Is the cast to convert struct pointed into its first member struct base* correct?
The code doesn't just casts, it also dereferences the pointer to the pointer to struct base. This is necessary to obtain the pointer to base in the first place.
This is what happens in your code, if the function tobase_pointed was removed:
struct pointed pt = {&em.base};
void* object = &pt; //pass to the function
struct base** bs = object; //the cast in the function
assert( bs == (struct base**)&pt ) ; //bs points to the struct pointed
assert( bs == &(pt.base) ) ; //bs also points to the initial member struct base* base
struct base* b = *bs ; //the dereference in the function
base_print(x);
bs is the pointer that was suitably converted to point to the initial member. Your code is correct.
This cast is justified, and you need it because you want to convert a pointer into a pointer to pointer. If you do not cast, dereference will be incorrect.
In other words, your base* has the same address as pt object. So you can access it through a pointer to pt. But you have to dereference it.

Allocating memory for structure types in C

Im having an issue in my program where I define a structure type but not a structure variable in a header as such.
typedef struct
{
int a;
int b;
int c;
Token d;
} Foo;
I then want to use this struct foo later on in a .c file that does infix to postfix
#include "header"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
int infix2postfix(char *infix, Arr arr)
{
struct Foo foo;
char szToken[MAX_TOKEN];
Stack stack = newStack();
infix = getToken(infix, szToken, MAX_TOKEN); //provides next token to be scanned by function.
... //push pop using switch case didn't post code for simplicity.
case...
push(stack, *foo.a);
...
case...
pop(stack);
...
goOut(arr, *foo.d); //goOut(function that populates and "arr" Array from printing.
}
So when I compile here I get
error: storage size of ‘foo’ isn’t known struct Foo foo;
I have tried struct Foo *foo = malloc(sizeof foo); to allocate memory but it messes up my push(stack, *foo.a); and goOut(arr, *foo.d); How do I go about fixing this? Do I have to allocate memory in the infix2postfix function first then declare a structure variable?
You defined a type Foo which is a tagless struct type. You could have a separate struct Foo { int anonymous; char name[MAX_NAME]; }; which is wholly unrelated to the type Foo. (It would be very confusing for humans, but the compiler would have no problem.)
In your function, you should write:
int infix2postfix(char *infix, Arr arr)
{
Foo foo;
you have already defined Foo as a typedef struct, so you do not use struct Foo again to declare foo, just use
Foo foo; to declare not struct Foo foo;

Function arguments within a function

I have the following code:
include <stdlib.h>
typedef struct foo{
int x;
}Foo;
void funcY(Foo *f1)
{
printf("%d", f1.x);
}
void funcX(Foo *f1)
{
printf("%d", f1.x);
funcY(f1); <---- is this correct?
}
int main()
{
Foo *foo1 = (struct foo *)malloc(sizeof(struct foo));
foo1.x = 10;
funcX(foo1);
return 0;
}
I don't know exactly how to label this problem. What is the best way for me to approach this?
funcY(f1); <---- is this correct?
Yes, this particular line is correct. However, several other parts that aren't: specifically, accessing struct members by pointer needs -> operator, rather than a dot:
printf("%d", f1->x);
Another small issue is that one should not cast malloc in C:
Foo *foo1 = malloc(sizeof(struct foo));
Finally, you are missing a call to free(foo) to deallocate malloc-ed memory. Note that you do not have to use malloc - allocate the struct in the automatic store, and use & to access its address:
int main()
{
Foo foo1;
foo1.x = 10;
funcX(&foo1);
return 0;
}
funcY(f1) is correct - it passes the Foo pointer to funcY, and since funcY accepts a Foo pointer we can assume it'll work as intended.
printf("%d", f1.x);, however, is not correct. f1 is a Foo pointer, not a Foo. To access it's x field you need to derefer it first - (*f1).x - or use the sytactic sugar f1->x.

Why does forward declaration of struct not work?

I wrote a small code in C in which two struct types were defined which have members of each other in their definition. Case 1: If the struct foo is defined before struct bar, the code is compiled as expected. Case 2: If struct foo is defined after struct bar it will not compile which is also expected as there is no way to know the memory requirement of a struct foo variable. But I was expecting it will compile if a forward declaration of struct foo is used in case 2. But it does not work. What am I missing?
#include<stdio.h>
#include<stdlib.h>
struct foo; // forward declaration
struct bar
{
int a;
struct bar *next;
struct foo ch;
};
struct foo
{
struct bar *n;
struct foo *nx;
};
int main()
{
struct bar p;
return(0);
}
forward declaration only informs the compiler that there is something that is called foo it does nothing says about size.
you can use foo* since this is a pointer of known size but not foo itself because the size is unknwon, so the compiler does not know how the memory layout of barshould look like.
And the compiler only do a single pass through your document. so it cannot know the strucutre that is defined ahead.
If a struct type X appears only as a pointer type in a structure declaration or its functions, and the code in the header file does not attempt to access any member variables of X, then you should not #include X.h, but instead make an incomplete declaration of X (also called a
"forward" declaration) before the first use of X. Here is an example in which a structure type Thing refers to X by a pointer:
struct X; /* incomplete ("forward") declaration */
struct Thing {
int i;
struct X* x_ptr;
};
The compiler will be happy to accept code containing pointers to an incompletely known structure type, basically because pointers always have the same size and characteristics regardless of what they are pointing to. Typically, only the code in the .c file needs to access the members (or size) of X, so the .c file will #include "X.h". This is a powerful technique for encapsulating a module and decoupling it from other modules.
That is, it would work correctly if your code was something like :
#include<stdio.h>
#include<stdlib.h>
struct foo; // forward declaration
struct bar
{
int a;
struct bar *next;
struct foo *ch; /* MODIFIED LINE */
};
struct foo
{
struct bar *n;
struct foo *nx;
};
int main()
{
struct bar p;
return(0);
}
But in your case, struct bar is having an "element" of type struct foo. Hence it will give error field has incomplete type.
Also for your information, see the below snippet (will work perfectly):
#include<stdio.h>
#include<stdlib.h>
struct bar
{
int a;
struct aabar *next; /* MODIFIED LINE - aabar never declared */
struct foo *ch;
};
struct foo
{
struct bar *n;
struct foo *nx;
};
int main()
{
struct bar p;
return(0);
}
A declaration also can't let the compiler know how to allocate the memory.
In your struct foo the element nx is a pointer, so defining struct foo doesn't require memery size. However, on struct bar the element ch is not a pointer, so the defining struct bar needs to know the size of struct foo. The forward declaration doesn't specify the memory size, the definition does.

Resources