how to pass a pointer to a pointer to a struct member? - c

So the problem at hand is to convert a string of digits in the format YYYYMMDD to
a struct tm type member within some other structure. Truth is, I really only care
about getting a struct tm with reasonable values in it.
Consider the following struct :
typedef struct some_node {
char somestring[64];
char anotherstring[128];
struct tm date_one;
struct tm date_two;
int some_val;
struct some_node *prev;
struct some_node *next;
} some_node_t;
Inside there I have two members of type struct tm from the time.h header. Seems
very reasonable. Also there are pointer members in there to make a linked list
however that isn't the issue.
So I create the first node in my yet to be created linked list like so :
/* begin the linked list of some_node_t */
struct some_node *t_head =
calloc( (size_t) 1, sizeof( some_node_t ) );
if ( t_head == NULL ) {
/*Memory allocation fault */
printf ( " FAIL : Memory allocation fault at %s(%d)\n",
__FILE__, __LINE__ );
exit ( EXIT_FAILURE );
}
/* I used calloc above which zero fills memory so these
* next lines are not really needed. Better safe than sorry. */
t_head->some_val = 0;
t_head->prev = NULL;
t_head->next = NULL;
Then I can stuff char data into the two char members :
strcpy ( t_head->somestring, "birthday" );
strcpy ( t_head->anotherstring, "19981127" );
No problem there.
Messing with the conversion of a string to a struct tm seems reasonable within a
function as I have to do it twice perhaps.
Therefore I write this :
int timestr_to_tm ( struct tm **date_val, char *yyyymmdd ) {
/* assume 8 digits received in format YYYYMMDD */
int j, date_status = -1;
char yyyy[5]="0000";
char mm[3]="00";
char dd[3]="00";
/* copy over the year digits first */
for ( j=0; j<4; j++ )
yyyy[j]=yyyymmdd[j];
/* month digits */
mm[0]=yyyymmdd[4];
mm[1]=yyyymmdd[5];
/* day digits */
dd[0]=yyyymmdd[6];
dd[1]=yyyymmdd[7];
*(date_val)->tm_year = atoi(yyyy) - 1900;
*(date_val)->tm_mon = atoi(mm) - 1;
*(date_val)->tm_mday = atoi(dd);
*(date_val)->tm_hour = 0;
*(date_val)->tm_min = 0;
*(date_val)->tm_sec = 0;
*(date_val)->tm_isdst = -1;
return 0;
}
So my hope here is that I can pass a pointer to a pointer to the member date_one
within t_node to that function.
if ( timestr_to_tm ( &(t_node->date_one), "19981127" ) < 0 ) {
/* deal with a bad date conversion */
}
Well my compiler has a fit here. Claiming :
error: argument #1 is incompatible with prototype:
Perhaps I should have &t_head->date_one but I think that the pointer dereference
operator "->" takes precedence over the "address of" operator. Perhaps it is bad
policy to even attempt to pass a pointer to a member within a struct?
Even worse, within the function timestr_to_tm() I get :
error: left operand of "->" must be pointer to struct/union
in those lines where I try to assign values into the struct tm variable.
I tried all this without passing pointers and the process works however upon
return there is nothing in the struct tm member. So I am wondering, what am
I missing here ?

If you really want to pass a pointer to a pointer to a struct tm, you can, you just need to create a pointer variable to hold the pointer and pass a pointer to that:
struct tm *pointer = &t_node->date_one;
if ( timestr_to_tm ( &pointer, "19981127" ) < 0 ) {
...
The question is why? You don't need the extra level of indirection as you're not trying to change the pointer, you just want to fill in the struct tm within the node. So just use a single pointer:
int timestr_to_tm ( struct tm *date_val, char *yyyymmdd ) {
:
date_val->tm_year = atoi(yyyy) - 1900;
:
then you can call it with a simple pointer and don't need to create an extra pointer variable:
if ( timestr_to_tm ( &t_node->date_one, "19981127" ) < 0 ) {
...

I think that the pointer dereference operator -> takes precedence over the "address of" operator
It does, so does it over the dereference, * operator. So this, for example:
*(date_val)->tm_mday = atoi(dd);
should be
(*date_val)->tm_mday = atoi(dd);
But: Why would you do this? Why not pass a pointer to the struct tm, and use -> without one more level of indirection?

Since I'm too lazy to understand the question, I'll just add this unrelated example which hopefully helps to clear things up. This is very straightforward, if you use the correct syntax and level of indirection.
typedef struct _node node_t;
struct _node {
node_t* next;
int a;
};
void fill_in_int(int* pointer_to_int) {
*pointer_to_int = 42;
}
void populate_all_nodes(node_t* list, int a_value) {
node_t* node;
for (node=list; node; node = node->next) {
fill_in_int( &(node->a) ); // Pass pointer to member a in node
}
}

Related

How to access struct members from pointer [duplicate]

This question already has answers here:
How to access members through a void pointer
(4 answers)
Closed 3 years ago.
I'm having trouble accessing a struct's members when passed a void* pointer to that structure's base address. Can anyone offer a solution or explain the error to me? Right now I get the message "goroutines.c:142:31: error: request for member ‘qtail’ in something not a structure or union"
//Channel struct
struct channel{
int magicnumber;
int length;
int capacity;
struct gcb* qhead; //head of the queue
struct gcb* qtail; //tail of the queue
};
void *makeChannel(int dataLength, int capacity){
if( dataLength <= 0){
panic( "data length must be greater than zero" );
}
if( capacity < 0){
panic( "capacity must be non-negative" );
}
struct channel* ch = (struct channel* )malloc( dataLength * capacity );
ch->magicnumber = 0x1ca91ac3;
ch->capacity = capacity;
ch->length = 0;
return ch;
}
void sendChannel(void *channel, void *fetchAddress){
if( capChannel( channel ) == lenChannel( channel ) ){
(struct channel* )&channel->qtail->next = head;
}
}
It's not valid to de-reference a void* pointer. The de-referencing is basically a numerical off-set from the base-pointer. If the compiler does not know what type the pointer is, how can it know the offset amount, nor is it able to decide whether the member reference is actually valid.
In your function it is cast, It looks like there's a stray &.
void sendChannel(void *channel, void *fetchAddress)
{
struct channel *chan = (struct channel *)channel;
if( capChannel( chan ) == lenChannel( chan ) )
{
chan->qtail->next = head;
}
}
But your cast is not applied to anything. I prefer to make the cast explicit, by assigning it to a temporary local variable. I feel this makes the resultant code more readable, as it's not full of type-casts here & there.
The operator -> has lower precedence and so is evaluated first. channel is a void pointer so, when channel-> de-references it, you obtain a value of type void instead of the expected struct channel.
Add parenthesis around the cast and channel (or pass channel around as a struct channel * rather than void* to avoid repeated casting):
((struct channel *)channel)->qtail->next = head;

"use of undeclared identifier" when typecasting void pointer to struct pointer

I am new to C and as a (classic) exercise I am trying to implement some operations on linked lists. I haven't gotten very far yet, though... When I am trying to declare and initialize the root node as follows:
#include <stdlib.h>
struct intNode_t {
int data;
struct intNode_t* next;
};
int main() {
struct intNode_t* root = ( intNode_t* ) malloc( sizeof( struct intNode_t ) );
return 0;
}
the compiler (clang) is giving me the error "use of undeclared identifier" at the place where I am trying to typecast the void pointer returned by malloc to a pointer to intNode_t. I realise this is a noob question, but I couldn't find the answer elsewhere. Any suggestions?
The names of structs in C occupy a separate namespace from the space of names of fundamental types and typedefs (see this question for details). Therefore, the name of your struct type is struct intNode_t; there is no type called intNode_t.
You can either always spell out the name as struct intNode_t, or you can create a type alias for it. There are many different patterns of this in real code:
Separate tag name, separate declaration:
typedef struct foo_t_ foo_t;
struct foo_t_ { /* ... */ };
This allows you to put the type alias in a header and publish it as an opaque API type without ever revealing the actual type definition.
Separate tag name, typedef in struct definition:
typedef struct foo_t_ { /* ... */ } foo_t;
Reuse name:
typedef struct foo_t { /* ... */ } foo_t;
This style allows users to be careless about spelling foo_t or struct foo_t.
Don't name the struct:
typedef struct { /* ... */ } foo_t;
However, in your code you don't actually need to repeat the name, since you should not cast the result of malloc and instead rely on the built-in implicit conversion from void pointer to object pointer. You also shouldn't repeat the type that's already known, and use the expression form of sizeof instead. So you want:
int main()
{
struct intNode_t* root = malloc(sizeof *root);
}
(Also note that return 0 is implied from main.)
No need to repeat yourself. If you don't repeat yourself you can make fewer errors.
struct intNode_t *root;
root = malloc( sizeof *root );
the cast is not needed; malloc() returns a void*, which is exchangeable with every (non-function) pointer type.
there are two syntax variants for sizeof: sizeof(type) and sizeof expression The first one needs (), the second one does not. Most people prefer the second form, because the expression (in your case *root ) always will yield the correct type, and thus: size.
And, the definition + assignment above can be combined into a definition + initialiser, all fitting on one line:
struct intNode_t *root = malloc( sizeof *root );
Name intNode_t was not declared in the program. There is declared structure tag name intNode_t.
So you need to write
struct intNode_t* root = ( struct intNode_t* ) malloc( sizeof( struct intNode_t ) );
Or you could introduce identifier name intNode_t the following way
typedef struct intNode_t {
int data;
struct intNode_t* next;
} intNode_t;
In this case you may write
struct intNode_t* root = ( intNode_t* ) malloc( sizeof( struct intNode_t ) );

Understanding pointer structs in C

I am trying to understand an assignment I have before I have to take a final. I am trying to understand what exactly I am declaring.
So in a given file the typedef struct's are declared as so:
(Struct Declaration)
/** The following two structs must be defined in your <gamename>.c file **/
typedef struct game_position_t *game_position;
/* move struct must code enough information to reverse the move, given the resulting position */
typedef struct move_t *move;
I have then built the structs out as so (yes this has to be separated just because it is interfaced programming):
(Struct Definition)
/** The following two structs must be defined in your <gamename>.c file **/
struct game_position_t {
int mathy;
int numrows;
int *sizes;
};
/* move struct must code enough information to reverse the move, given the resulting position */
struct move_t {
int rownum;
int move_size;
};
Then an example of a functions and declaration of game_position for example is:
(Example Function)
/* return the starting position, NULL if error */
game_position starting_position(int me_first, int argc, char **argv) {
if (argc < 3) {
printf("\n\nToo few arguments, see help below\n\n");
game_help(argv[0]);
return NULL;
}
int mathy;
if (strcmp(argv[2],"search")==0)
mathy = 0;
else if (strcmp(argv[2],"mathy")==0)
mathy = 1;
else {
printf("\n\nSecond argument must be \"search\" or \"mathy\", see help below\n\n");
game_help(argv[0]);
return NULL;
}
int play_default = (argc==3);
if (play_default) printf("\n\nOK, we will play the default game of 7 5 3 1\n\n");
int defaultgame[4] = {7,5,3,1};
game_position result = malloc(sizeof(struct game_position_t)*1);
result->mathy = mathy;
if (result) {
result->numrows = (play_default ? 4 : argc-3);
result->sizes = malloc(sizeof(int)*(result->numrows));
int row;
for (row=0; row<(result->numrows); row++)
(result->sizes)[row] = (play_default ? defaultgame[row] : strlen(argv[row+2]));
}
return result;
}
So my main misunderstanding is when using a struct declaration in this manner, specifically putting the * before the name like this, typedef struct move_t *move;. Is that previous line saying move it a struct pointer or dereferencing move? Continuing from that. When defining them I just use the struct name such as struct move_t. I don't fully understand how they are linking together and in what matter. Then inside the function I just declare game_position, but still need to use a derefencer, 'p->`, to access it fields. So if someone could explain to me when these struct variables are points to structs and when they are the actual struct.
An example of my misunderstanding is that in the Example Function after result was declared. I first thought to use the . operator to access and set it's fields. I then changed it due to compiler errors, but now I want to understand my misunderstanding. And why did I I have to malloc game_position_t and not game_position?
typedef defines a type, so typedef struct move_t *move defines a new type named move, which is a pointer type, pointing to struct move_t. So after this if you define a variable with move ptr, ptr will have a pointer type so that you should use the syntax of accessing members through a pointer. When allocating memory for it, of course you have to specify the exact size of the structure other than the size of a pointer, that's sizeof(struct move_t)

C99 pointer to a struct which contains a pointer to a 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. :-)
Isn't this sufficient?
node_head->tv->tv_sec
the other answers have it, but in case it's not clear, -> is the same as doing a "dereference" with a * yourself.
so
rp->pt1
(*rp).pt1
are equivalent.
which means that you have the rule of thumb "use -> when dealing with pointers".
so in the case you had,
node_head->tv->tv_sec
will do what you want, and is equivalent to
(*node_head).tv->tv_sec
(*(*node_head).tv).tv_sec
You should change (*node_head.tv) to (*node_head).tv (or node_head->tv as Oli wrote) as . has higher precedence over *.
An initial remark: your (struct timespec *) cast of tv is not necessary, since that is already how tv is declared.
As others have indicated, you really only need to use the ptr->field notation here: node_head->tv->tv_sec. The -> notation is a bit of syntactic sugar to avoid all the (*rp).(*pt1).x clumsiness which would otherwise be required.
You asked,
Well what is the definition of rect were such that pt1 and pt2 were
both pointers to a struct point?
in that case #teppic's solution is what you want, but one subtlety to keep in mind is where the actual memory for the data structure is being allocated: in your example, the actual memory allocation is in rect, and in #teppic's, it's point. This point, sometimes tricky for newcomers to C, matters, particularly when you allocate and free the memory many times in long-running programs (necessary to avoid memory leaks).
From your opening example, if you have instead:
struct rect {
struct point *pt1;
struct point *pt2;
};
struct point {
int x;
int y;
};
and you have
struct rect *rp;
Then to access x you just use:
rp->pt1->x
The compiler can figure out what's going on. You only need casting if you have void pointers and such.

How to access union inside structure?

I have the following code:
/* sample.c */
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include"hermes.h"
#include<string.h>
int main (){
struct hermes *h ;
h = ( struct hermes *) malloc ( sizeof ( struct hermes *));
strcpy ( h->api->search_response->result_code , "123" );
printf("VALue : %s\n" , h->api->search_response->result_code );
return 0;
}
/* hermes.h */
struct hermes {
union {
/* search response */
struct {
int error_code;
char *result_code;
char *user_track_id;
struct bus_details bd;
}*search_response;
}*api;
};
I get a segmentation fault when I try to access the elements. Could anyone tell me what is the right way to access these elements?
Your malloc() line isn't correct:
h = ( struct hermes *) malloc ( sizeof ( struct hermes *));
should be:
h = ( struct hermes *) malloc ( sizeof ( struct hermes));
Remove the * in the sizeof(). Otherwise, you're only allocating enough for a pointer rather than the struct itself.
Also, the cast isn't necessary in C.
Use this struct:
#define MAX 512 /* any number you want*/
struct hermes {
union {
/* search response */
struct {
int error_code;
char result_code[MAX];
char user_track_id[MAX];/* can use different sizes too*/
struct bus_details bd;
}search_response[MAX];/* can use different sizes too*/
}*api;
};
Or if you want to use your current struct, malloc the pointer element like:
h->api = malloc((sizeof(int)+sizeof(char)*MAX*2+sizeof(struct bus_details))*MAX)
It's not a problem of accessing the elements. That's about all that you are doing correctly.
Here are some of the things that are wrong. First, you aren't allocating enough space for a hermes struct, just enough for a pointer. Then, even if you malloc( sizeof ( struct hermes ) );, the one element (api) is an uninitialized pointer. You can't just follow uninitialized pointers down deep into the data structure, because they will be pointing to who knows where in memory. You first need to allocate something for h->api to point to. Then you need to allocate space for h->api->search_response. If you correct all that, then you are copying a string to ... who knows where? You should use strdup, not strcpy to create a new string, then you should assign the return value to result_code. Also, your union has only one element, so it's kind of pointless (unless there's more to it that you haven't posted).
EDIT Here's one way of initializing h:
h = malloc( sizeof( struct hermes ) );
h->api = malloc( sizeof( *h->api ) );
h->api->search_response = malloc( sizeof( h->api->search_response ) );
h->api->search_response->result_code = strdup( "123" );
Note that in a well-behaved program that cleans up after itself, each of these allocations will have to be freed individually as well, in reverse order of the calls to malloc. Since you immediately call exit(0), no harm is done in this case if you don't.

Resources