Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C99 pointer to a struct which contains a pointer to a struct

Tags:

c

pointers

struct

The K&R "The C Programming Language" 2nd edition says on page 131 given a set of variables thus :

struct rect r, *rp = &r;

where :

struct rect {
    struct point pt1;
    struct point pt2;
};

and

struct point {
    int x;
    int y;
}

then these four expressions are equivalent :

r.p1.x
rp->pt1.x
(r.pt1).x
(rp->pt1).x

Earlier on that same page we see this :

p->member_of_structure

Which is described as "refers to the particular member".

I changed the hyphens to underscores to ensure we could not be confused with a minus sign.

So great, I can see we have what I would refer to as a nested struct because the struct rect contains within it a struct point.

Well what is the definition of rect were such that pt1 and pt2 were both pointers to a struct point?

Here is where I hit my troubles with the following code bits :

typedef struct some_node {
    struct timespec *tv;
    struct some_node *next;
} some_node_t;

Clearly I will be making a linked list here and that is no problem.

What is a really big problem is this :

struct timespec some_tv;
clock_gettime( CLOCK_REALTIME, &some_tv )
/* set up the head node */
struct some_node *node_head =
                ( struct some_node * ) malloc( sizeof( some_node_t ) );
node_head->tv = calloc ( (size_t) 1, sizeof ( struct timespec ) );

That all works great and I get my node_head just fine. I even get my nested struct timespec node_head->tv just fine.

What is a real problem is trying to figure out how to set that inner tv.sec to the value in some_tv.sec like so :

((struct timespec *)(*node_head.tv)).tv_sec = some_tv.tv_sec;

I get an error :

line 22: error: left operand of "." must be struct/union object

So I am looking in the K&R and I see that the example in the book does not have a pointer to a struct within the struct rect.

I have resorted to trial and error to get what I want but this is maddening. I could create a temporary variable of type "struct timespec temp" and then set temp = &node_head.tv ... but no ... that won't work. That would be worse I think.

What am I missing here ?

The answer was trivial, of course, simply use foo->bar->here syntax.

Modify the code to drop the cast on the malloc and use the correct syntax :

/* set up the node list */
struct some_node *node_head =
                calloc( (size_t) 1, sizeof( some_node_t ) );

node_head->tv = calloc ( (size_t) 1, sizeof ( struct timespec ) );
node_head->tv->tv_sec = some_tv.tv_sec;
node_head->tv->tv_nsec = some_tv.tv_nsec;
node_head->next = NULL;

The debugger confirms this :

(dbx) print *node_head
*node_head = {
    tv      = 0x1001453e0
    next    = (nil)
}

(dbx) print *node_head.tv
*node_head->tv = {
    tv_sec  = 1363127096
    tv_nsec = 996499096
}

Works great. clearly, I need coffee. :-)

like image 344
paul lanken Avatar asked Mar 03 '26 03:03

paul lanken


1 Answers

Isn't this sufficient?

node_head->tv->tv_sec
like image 190
Oliver Charlesworth Avatar answered Mar 04 '26 17:03

Oliver Charlesworth