How to access containing structure from a member in C? - c

I'm working with a few kernel modules (4.19.97) and I allocate struct my_sock like the following.
struct my_target {
union thingA { ... } a;
struct thingB *b;
};
struct my_sock {
struct sock sk;
// ...
struct my_target target;
};
struct my_sock *my_s;
my_s = my_sock_alloc();
// ...
my_s->sk.sk_prot->init(sk);
The above ends up calling this callback.
static int my_init(struct sock *sk)
{
// I do the following because I cannot pass in the allocated
// `struct my_sock` into this function.
struct my_sock *ms = my_sk(sk);
// I want to access my_s->my_target or any field within
// `struct my_target` here, but at this point, `ms` is
// pointing to the the first member of `struct my_sock`, and
// not the originally allocated `my_s`.
ms->target.a;
}
static inline struct my_sock* my_sk(const struct sock *s)
{
return container_of(s, struct my_sock, sk);
}
// Here's how my_s gets allocated. Note that this is not the same
// structure as the first member of `struct my_sock`.
struct my_sock* my_sock_alloc(void)
{
struct my_sock *sk = NULL;
sk = kmem_cache_zalloc(my_sk_cachep, GFP_KERNEL);
if (!sk)
return NULL;
return sk;
}
And here's the problem. The kernel has the code for container_of within include/linux/kernel.h which casts a member of a structure out to the containing structure, per the commentary.
When I use my_sk(sk), I get the pointer address of the first member of the containing struct. The problem is that this is a different address than my_s which I allocated in the very first line and I need the pointer to my_s in order to access the target member.
Thoughts as to how I might access my_s->target within the call my_init() (and not make things global)?

since sk is the very first field in struct my_sock, you can just cast the pointer and things should work:
struct my_sock *ms = (struct my_sock *)sk;
the extra work done in container_of is only needed when the "base" struct is not the first field.

Related

Writing an Address to a Pointer in a struct with a function fails

I have two structs pbuf and netif, and assigned two variables (local_pbuf, local_netif) with them. These variables hold some data. There is another struct called wrapper_p_n, which holds two pointers of the type pbuf and netif. My goal is to write a function which hand over the variables local_pbuf and local_netif by call by reference and then wraps the two pointers in a single struct called wrapper_p_n. Then I want to use call by reference to give wrapper_p_n to another function. Unfortunately I get the Error message:
[Error] cannot convert 'pbuf**' to 'pbuf*' in assignment
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
struct pbuf{
int a;
int b;
};
struct netif{
int c;
int d;
};
struct wrapper_p_n{ // wrapper for pbuf- and netif-struct pointer
struct pbuf *wp_val_p;
struct netif *wp_val_n;
};
void rx_local_p_n(struct pbuf *rx_pbuf, struct netif *rx_netif)
{
// wrap the received pointer
struct wrapper_p_n *local_w_p_n;
local_w_p_n->wp_val_p = &rx_pbuf;
local_w_p_n->wp_val_n = &rx_netif;
/*Passing *local_w_p_n pointer to another function: Example: */
/*ex_function(&local_w_p_n)*/
}
int main(int argc, char** argv) {
// give values to local_pbuf and netif
struct pbuf local_pbuf;
local_pbuf.a = 1;
local_pbuf.b = 2;
struct netif local_netif;
local_netif.c = 3;
local_netif.d = 4;
//passing pbuf- and netif-stuct to function
rx_local_p_n(&local_pbuf, &local_netif);
return 0;
}
In the function void rx_local_p_n you pass in pointers to the pbuf and netif struct. These are already pointers and do not need to be assigned to your wrapper struct using the address of operator (&): by doing so you are getting the memory location of the pointer itself. That is why it is complaining about not being able to convert pbuf** to pbuf*.
Solution
local_w_p_n->wp_val_p = &rx_pbuf; to local_w_p_n->wp_val_p = rx_pbuf;
local_w_p_n->wp_val_n = &rx_netif; to local_w_p_n->wp_val_n = rx_netif;
Here in the function params,
struct pbuf *rx_pbuf, struct netif *rx_netif
Are already pointers, you do not need to get the address of the pointers, the & is useful when your variables are allocated on the stack and the function call needs a pointer.
As a result, this is the code change
local_w_p_n->wp_val_p = rx_pbuf;
local_w_p_n->wp_val_n = rx_netif;
In the original posted code local_w_p_n was defined as a pointer but not initialized; the attempts to assign members should crash since local_w_p_n would be leftover stack data, not a valid address. Try this example:
void rx_local_p_n(struct pbuf *rx_pbuf, struct netif *rx_netif)
{
// define as a struct instead of a struct *
struct wrapper_p_n local_w_p_n;
// assign from func args without &
// switch from -> to .
local_w_p_n.wp_val_p = rx_pbuf;
local_w_p_n.wp_val_n = rx_netif;
x_function(&local_w_p_n);
}

Accessing a member in a nested structure

Is there a way to access individual members of a structure that is nested inside two other structures without using the dot operator multiple times?
Unlike some variants of BASIC or Pascal that have a with keyword which allows you to access inner members of a structure directly, C has no such construct.
You can do this however with pointers. If you have a particular inner member you're going to access frequently, you can store the address of that member in a pointer and access the member through the pointer.
Suppose for example you had the following data structures:
struct inner2 {
int a;
char b;
float c;
};
struct inner1 {
struct inner2 in2;
int flag;
};
struct outer {
struct inner1 in1;
char *name;
};
And a variable of the outer type:
struct outer out;
Instead of accessing the members of the innermost struct like this:
out.in1.in2.a = 1;
out.in1.in2.b = 'x';
out.in1.in2.c = 3.14;
You declare a pointer of type struct inner2 and give it the address of out.in1.in2. Then you can work directly with that.
struct inner2 *in2ptr = &out.in1.in2;
in2ptr->a = 1;
in2ptr->b = 'x';
in2ptr->c = 3.14;
Is there a way to access individual members of a structure that is nested inside two other structures without using the dot operator multiple times?
No. Not via standard C.
To make the accessing code cleaner however, you might consider some static inline helper functions.
For example:
struct snap {
int memb;
};
struct bar {
struct snap sn;
};
struct foo {
struct bar b;
}
static inline int foo_get_memb(const struct foo *f)
{
return f->b.sn.memb;
}
Not completely answering your question.
The 1st member of any struct can be accessed by taking the struct's address, casting it to a pointer type pointing to the struct's 1st member and dereferencing it.
struct Foo
{
int i;
...
};
struct Foo foo = {1};
int i = *((int*) &foo); /* Sets i to 1. */
Adapting this to nested struct's gives us for example:
struct Foo0
{
struct Foo foo;
...
};
struct Foo1
{
struct Foo0 foo0;
...
};
struct Foo2
{
struct Foo1 foo1;
...
};
struct Foo2 foo2;
foo2.foo1.foo0.foo.i = 42;
int i = *((int*) &foo2); /* Initialises i to 42. */
struct Foo0 foo0 = {*((struct Foo*) &foo2)}; /* Initialises foo0 to f002.f001.foo0. */
This is well defined, as the C-Standard guarantees that there is no padding before a struct's 1st member. Still it's not nice.
You could use the -> operator.
You could take the address of an inner member and then access it via the pointer.

Is it possible to create a function ( in C ), that can operate with different structure?

i'm looking for creating a function in C language that allows me to receive different structures type as parameters.
For example, if I create 3 different structures
struct a{
struct datatype0{
char test1[10];
}datatype;
struct a *next;
};
struct b{
struct datatype1{
int test1;
char test2[20];
int test3;
}datatype;
struct b *next;
};
struct c{
struct datatype2{
char test1;
char test2;
float test3;
int test4;
int test5;
}datatype;
struct c *next;
};
I wanna create a function that can receives one of theese three different struct as parameter, so I can call only it for initialize first, or second or third kind of structure:
void function("---")//<-- inside the brackets i need to insert a parameter that can be struct a, or struct b or struct c.
{
//here for example I can insert the initialize function that have to work with any struct.
}
I tryed to use a union, but I saw that I have to recreate the initializing function for each kind of struct...I tryed to use void pointers, but i need to cast theese inside the function and I need to create initializing function for each kind of struct too...
Any ideas??
The long and short of it is: avoid to do this whenever possible, but know that you Can pass different structs to a single function if you really have to.
Probably the easiest way is to create a wrapper struct, that contains 2 members: a union, and a flag to let you know which struct is passed.
typedef enum {
A,
B,
C
} struct_type;
struct _wrapper {
union {
struct a A;
struct b B;
struct c C;
};
struct_type flag;
};
void my_function(struct _wrapper *data)
{
switch (data->flag)
{
case A:
struct a val = data.A;
//do stuff with A
break;
case B:
struct b val = data.B;
break;
case C:
struct c val = data.C;
//...
break;
}
}
Another option, although it's considered bad practice, and is something you'll end up regretting is to rely on the fact that the offset of the first member of any struct is guaranteed to be 0. You can cast a pointer to any struct to a pointer to its first member. If the first member of all structs is compatible, you can rely on that (at your own risk).
One way of exploiting this is to set a function pointer as first member, or an enum field that you can use as a flag to identify the struct:
struct a {
void (*common_member)();//
/** other members **/
};
struct b {
void (*common_member)();//needn't be the same name though
/** other members **/
};
Then:
void my_func(void *data)
{//void pointer
((void (*)(void *))data)(data);//cast void *data to function pointer, and pass itself as an argument
}
This can work, if the structs are properly initialized, and the members point to the correct functions, but that's too many if's to rely on really.
Using the enum as first member is slightly less risky, but still not to be recommended. It's a sort of a combination of the function pointer and union approach
void my_func(void *data)
{
//cast void * to struct_type *, dereference AFTER the cast
//because you can't dereference a void *
switch(*((struct_type *) data))
{
case A: /* stuff */ break;
case B: /* struct b */ break;
}
}
All in all, use the first approach. Do not use the function pointer members, and acknowledge the third approach for what it is: true, you don't need a wrapper struct, but it's not that much safer than the original approach (function pointers), and no less verbose than the first approach (with union).
Bottom line: structs and unions are the way to go
In part it works. But for example, if I wanna create a function like:
typedef union elemento{
struct a A;
struct b B;
struct c C;
}elemento;
void inserimentoOrdinato(elemento dausare){
struct b prova;
prova.datatype.test1 = 3;
strcpy(prova.datatype.test2,"TESTA");
prova.datatype.test3 = 200;
prova.next = (struct a*)malloc(sizeof(struct a));
dausare.B = prova;
}
I need to use "dausare.B" or "dausare.C" for the different kinds of structures. It doesn't know itseflt which part of union has to use. Am I rigth? Thank you!
The answer is generic programming and function pointer:
**void * can be a pointer to any struct
Declaration part:
typedef void *Initializer(void* obj);//since every struct has its own fields to initialize
void function(void * obj, Initializer init)
{
init(obj);
}
Usage:
void InitA(void* a_void)
{
struct a* a = (struct a*) a_void;
//init a feilds
a->next = NULL;
}
void InitB(void* b_void)
{
struct b* b = (struct b*) b_void;
//init b feilds
b->next = NULL;
}
void InitC(void* c_void)
{
struct c* c = (struct c*) c_void;
//init a feilds
c->next = NULL;
}
int main()
{
struct a a;
struct b b;
struct c c;
Init(&a,InitA);
Init(&b,InitB);
Init(&c, initC);
return 0;
}
***Keep in mind that you dont have to build a different function for each struct if they have the same fields to initialize.

request for member 's' in something not a structure or union

I'm trying to use an array of structs and everytime I try to assign a value to any struct, it gives me this error:
request for member 's' in something not a structure or union
My struct:
struct {
char s;
int lineNum;
} item;
I'm declaring it this way:
struct item * stack[100];
And then:
/* both lines gives me the error */
stack[0].s = 'a';
stack[0].lineNum = 1;
Am I missing something here?
You do not have a struct item.
stack is an array of 100 pointer to an as yet undefined struct.
Try
struct item {
char s;
int lineNum;
};
You need this:
struct item {
char s;
int lineNum;
} ;
...
struct item * stack[100];
...
stack[0]->s = 'a';
stack[0]->lineNum = 1;
but beware: you need to allocate memory for each item in stack. stack contains 100 pointers to struct items, but each of these pointers contains garbage (they all point to invalid memory).
For each element in stack you need to allocate memory like this stack[n] = malloc(sizeof struct item).
struct item stack[100] is what you want for your code that follows. What you have is an array of pointers, each of which if you wish to use, you will need to allocate, before your declaration.
You have not defined struct item. You currently have a single variable named item of an anonymous struct. It appears you forgot to include the typedef:
typedef struct { ... } a_t; // can use "a_t" as type.
struct a { ... }; // can use "struct a" as type.
typedef struct a { ... } a_t; // can use "struct a" or "a_t" as type.
stacks is not an array of items, it's an array of pointers to items, so you need to dereference them before attempting to use them:
(*(stack[0])).s = 'a';
(*(stack[0])).lineNum = 1;

What's wrong in this allocation?

This the struct that I declared :-
struct page_table_entry {
struct addrspace* as;
vaddr_t va;
//page_state_t state;
int timestamp;
};
Now I want to dynamically allocate memory for an array of this. My implementation is here :-
struct page_table_entry **coremap = (struct page_table_entry**)
kmalloc(npages*sizeof(struct page_table_entry*));
int i;
for(i=0;i<npages;i++)
{
coremap[i] = (struct page_table_entry*)kmalloc(sizeof(struct page_table_entry));
coremap[i].va=(firstAddress+(i*PAGE_SIZE));
}
Its giving me an error on the last line where I am accesing the variable va. Error is:-
error: request for member `va' in something not a structure or union
You have an array of pointers to structs, not an array of structs.
In the line
coremap[i] = (struct page_table_entry*)kmalloc(sizeof(struct page_table_entry));
you cast your memory allocation to page_table_entry*, so coremap[i] is this pointer.
You access the actual struct via
coremap[i]->va=(firstAddress+(i*PAGE_SIZE));
coremap is a pointer to a pointer to a struct page_table_entry.
When you dereference it with coremap[i] you get a pointer to a struct page_table_entry.
You cannot use . on a pointer to a structure. You must use ->:
coremap[i]->va=(firstAddress+(i*PAGE_SIZE));
or
(*coremap[i]).va=(firstAddress+(i*PAGE_SIZE));
Aside from the obvious change to coremap[i]->va, you could change to an array of structs:
struct page_table_entry *coremap = (struct page_table_entry*)kmalloc(npages*sizeof(struct page_table_entry));
int i;
for(i=0;i<npages;i++)
{
coremap[i].va=(firstAddress+(i*PAGE_SIZE));
}

Resources