Converting a pointer to a struct to its first member - c

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.

Related

Does dereferencing a cast to an anonymous structure pointer violate strict aliasing?

I have heard conflicting things about the extent to which the C standards guarantee structure layout consistency. Arguments for a limited extent have mentioned strict aliasing rules. For example, compare these two answers: https://stackoverflow.com/a/3766251/1306666 and https://stackoverflow.com/a/3766967/1306666.
In the following code I assume in all structures foo, bar, and struct { char *id; } that char *id is in the same place, making it safe to cast between them if it is the only member accessed.
Regardless of whether the cast will ever result in an error, does it violate strict aliasing rules?
#include <string.h>
struct foo {
char *id;
int a;
};
struct bar {
char *id;
int x, y, z;
};
struct list {
struct list *next;
union {
struct foo *foop;
struct bar *barp;
void *either;
} ptr;
};
struct list *find_id(struct list *l, char *key)
{
while (l != NULL) {
/* cast to anonymous struct and dereferenced */
if (!strcmp(((struct { char *id; } *)(l->ptr.either))->id, key))
return l;
l = l->next;
}
return NULL;
}
gcc -o /dev/null -Wstrict-aliasing test.c
Note gcc gives no errors.
Yes, there are multiple aliasing-related issues in your program. The use of the lvalue with anonymous structure type, which does not match the type of the underlying object, results in undefined behavior. It could be fixed with something like:
*(char**)((char *)either + offsetof(struct { ... char *id; ... }, id))
if you know the id member is at the same offset in all of them (e.g. they all share same prefix). But in your specific case where it's the first member you can just do:
*(char**)either
because it's always valid to convert a pointer to a struct to a pointer to its first member (and back).
A separate issue is that your use of the union is wrong. The biggest issue is that it assumes struct foo *, struct bar *, and void * all have the same size and representation, which is not guaranteed. Also, it's arguably undefined to access a member of the union other than the one which was previously stored, but as a result of interpretations in defect reports, it's probably safe to say it's equivalent to a "reinterpret cast". But that gets you back to the issue of wrongly assuming same size/representation.
You should just remove the union, use a void * member, and convert the value (rather than reinterpret the bits) to the right pointer type to access the pointed-to structure (struct foo * or struct bar *) or its initial id field (char *).

Pointers to pointers to structures

Hi have a function which takes the argument of a pointer, to a pointer to a struct. I'm having trouble accessing the members of my struct. Do struct pointers behave differently to pointers of other types, or am i just missing somethign essential?
struct mystr {
int num;
};
void fun(mystr **out) {
printf("%d",**out.num); <-- where the problem arises
}
No, 'struct pointers' (whatever you mean) work precisely the same way as pointers to other types.
You just need to recall operators precedence:
. structure member access
->structure member access through pointer
(...)
* indirection (dereference)
(...)
So your expression **out.num is interpreted as *(*(out.num)) and your (out.num) is not a pointer, hence applying an asterisk to it is an error.
You need to parenthesise appropriate part of the expression to force a non-default operators binding: (**out).num – dereference out twice first to get to a struct mystr variable, then access that variable's num member.
The -> operator serves as a shortcut for accessing a member of pointed stucture:
(ptr_expr)->member_name is equivalent to (*(ptr_expr)).member_name
so you can replace (**out).num with (*out)->num.
Possible to the solution to use this :
printf("%d",(*out)->num);
instead of
printf("%d",**out.num);
This is the way you should implement, here printf("%d",(*(*out)).num); will print 1.
#include<stdio.h>
#include<stdlib.h>
struct mystr{
int num;
};
void fun(struct mystr **out) {
printf("%d",(*(*out)).num);
}
int main()
{
struct mystr m;
struct mystr *p;
struct mystr **pp;
p=&m;
pp=&p;
m.num=1;
fun(pp);
return 0;
}
Here m is our structure, p is pointer to structure and pp is pointer to the pointer p.

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

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.

Casting struct * to int * to be able to write into first field

I've recently found this page:
Making PyObject_HEAD conform to standard C
and I'm curious about this paragraph:
Standard C has one specific exception to its aliasing rules precisely designed to support the case of Python: a value of a struct type may also be accessed through a pointer to the first field. E.g. if a struct starts with an int , the struct * may also be cast to an int * , allowing to write int values into the first field.
So I wrote this code to check with my compilers:
struct with_int {
int a;
char b;
};
int main(void)
{
struct with_int *i = malloc(sizeof(struct with_int));
i->a = 5;
((int *)&i)->a = 8;
}
but I'm getting error: request for member 'a' in something not a struct or union.
Did I get the above paragraph right? If no, what am I doing wrong?
Also, if someone knows where C standard is referring to this rule, please point it out here. Thanks.
Your interpretation1 is correct, but the code isn't.
The pointer i already points to the object, and thus to the first element, so you only need to cast it to the correct type:
int* n = ( int* )i;
then you simply dereference it:
*n = 345;
Or in one step:
*( int* )i = 345;
1 (Quoted from: ISO:IEC 9899:201X 6.7.2.1 Structure and union specifiers 15)
Within a structure object, the non-bit-field members and the units in which bit-fields
reside have addresses that increase in the order in which they are declared. A pointer to a
structure object, suitably converted, points to its initial member (or if that member is a
bit-field, then to the unit in which it resides), and vice versa. There may be unnamed
padding within a structure object, but not at its beginning.
You have a few issues, but this works for me:
#include <malloc.h>
#include <stdio.h>
struct with_int {
int a;
char b;
};
int main(void)
{
struct with_int *i = (struct with_int *)malloc(sizeof(struct with_int));
i->a = 5;
*(int *)i = 8;
printf("%d\n", i->a);
}
Output is:
8
Like other answers have pointed out, I think you meant:
// Interpret (struct with_int *) as (int *), then
// dereference it to assign the value 8.
*((int *) i) = 8;
and not:
((int *) &i)->a = 8;
However, none of the answers explain specifically why that error makes sense.
Let me explain what ((int *) &i)->a means:
i is a variable that holds an address to a (struct with_int). &i is the address on main() function's stack space. This means &i is an address, that contains an address to a (struct with_int). In other words, &i is a pointer to a pointer to (struct with_int). Then the cast (int *) of this would tell the compiler to interpret this stack address as an int pointer, that is, address of an int. Finally, with that ->a, you are asking the compiler to fetch the struct member a from this int pointer and then assign the value 8 to it. It doesn't make sense to fetch a struct member from an int pointer. Hence, you get error: request for member 'a' in something not a struct or union.
Hope this helps.

What does the notation (((nodeptr) (bodyptr)) -> type) mean in C?

I came across a piece of code that looks like this, where nodeptr and bodyptr are pointers to a struct, and type is a member of the struct.
#define Type(x) (((nodeptr) (x))->type)
What does it mean to have two pointers next to each other in brackets? I get that the -> notation gets the member of the struct, but am not sure about the first part of the line. I'm fairly new to C and am trying to get my head around pointers!
It's a cast.
In this part, ((nodeptr)(bodyptr)), The pointer bodyptr is casted as pointer of type nodeptr, then it accesses the member type of the structure pointed to by bodyptr.
I.e.
void *GetStructPtr(void); //The function returns a pointer to void
typedef struct //This is our structure
{
float a;
int type;
} node;
type def node *nodeptr; //This is our pointer type
void my func(void)
{
void *bodyptr; //Here we have a generic void pointer
bodyptr = GetStructPtr(); //Assign to it the vallue returned from function
//In the next line we cast our void* to a pointer to a structure node
//and then access its member type.
((nodeptr)bodyptr)->type = 0;
}
In your case it has been inserted in a macro to make it easier to use.
It is cast. The pointer bodyptr is being casted to nodeptr and then type member accessed. This means that instead of accessing type member directly from bodyptr it is first converted to pointer of type nodeptr and only then accessed. It is useful e.g. when first pointer is just a pointer to raw memory, of type void * and you want to treat this memory as given type, maybe some struct.
Example:
struct e {
int a;
double b;
};
struct e foo { 1, 2.0 };
void *pFoo = &foo; // p points at foo now
// I know p is now address of object of type struct e
// and I want to get it's 'a' element BUT I can't
// do p->a, p is of void* type, yet I can do
int a = ((struct e*)(pFoo))->a;

Resources