Pointer to table of struct in C - c

I don't understand some piece of code in C, and couldn't find any similar question, so I hope you'll help me.
I have a struct table defined like this:
struct my_struct {
struct other_struct some_struct[N];
char some_char;
..
} my_struct[N];
In another function:
struct my_struct *ms;
And then is the part I don't understand:
ms = &my_struct[0];
How can I interpret this line?

ms is a pointer to the struct my_struct. It contains address of a struct my_struct variable. Here we assign to ms the already declared struct my_struct array's (also name my_struct) 0-th element's address.
& - address of operator. Which basically returns the address of a variable.
Now you can access my_struct[0] via ms.
Equivalently
ms->some_char = 'A' is same as my_struct[0].some_char='A'. To give a small example I can simplify this way.
struct a{
int z;
};
struct a array[10]; // array of 10 `struct a`
struct a* ptr = &array[0]; // ptr contains the address of array[0].
Now we can access array[0] via pointer ptr.
And ms is just a pointer to struct not pointer to a table of struct as you have mentioned in the question heading.

Related

C structure pointer to a structure array, from a structure

I need some help with the pointer syntax. I have an array of structures, and I'm trying to create a pointer to it, from inside another structure, contained in an array.
struct foo array* = malloc(sizeof(foo)*10);
bar_arr[i]->foo_ptr = &array;
I have read through this question: c pointer to array of structs. While it did clear up some of the confusion, I'm still left with a few errors to solve.
I have defined my structure like this:
struct bar{
...
struct foo (*foo_ptr)[];
...
}
It seems that I am able to add new structures to the array, as the following returns no errors:
(*bar_arr[i]->foo_ptr)[j] = new_struct;
However, if I attempt to create a new pointer to a struct inside of the struct array like this:
struct foo* one_ptr = (*bar_arr[i]->foo_ptr)[j];
or this:
struct foo* one_ptr = bar_arr[i]->foo_ptr[j];
the compiler will give me errors. Either one for invalid use of an array with unspecified bounds, or that one_ptr and foo_ptr[j] have incompatible types (in this case: one is of type foo and the other is struct foo *).
Is it simply not possible to create a pointer to one of the elements of the structure array? Any help would be appreciated.
EDIT: BETTER CODE EXAMPLE
I am currently working with a linearly linked list for use as a shared memory stack, for use with pthreads. The array of structures is a shared pool of nodes. Whenever a node is removed from the stack, it is put into the shared pool. If a thread attempts to add a new item to the stack, it checks whether or not the element to be added exists in the pool, to avoid having to allocate new memory every time it needs to add another element to the stack.
Each thread needs a pointer to the shared pool of nodes as an argument. That's why i'm trying to create a pointer to it from the argument structure. I was hoping that the question would have a simple answer.
typedef struct node{...} node_t;
struct thread_args
{
...
node_t (*pool)[];
...
}
node_t shared_pool = malloc(sizeof(node_t)*10);
arg[index]->pool = &shared_pool;
I am trying to access the pool inside one of the functions that the thread is executing.
node_t *item;
item = stack->root;
//remove item from stack
(*args->pool)[index] = item;
//...later
node_t *item2;
item2 = (*args->pool)[index];
Hopefully this provides some more information.
Also, the exact error i get from attempting to use:
node_t *pool;
args[index]->pool = shared_pool;
is as follows: error: incompatible types when assigning to type ‘struct node_t *’ from type ‘node_t’.
For starters this declaration (not mentioning the omitted semicolon after the closing brace)
struct bar{
...
struct foo (*foo_ptr)[];
^^^
...
}
is invalid. You have to specify the size of the array. Otherwise the pointer will point to an object of an incompete type.
Taking into account how you are trying to use the array this declaration does not make sense. You could declare the data member like
struct bar{
...
struct foo *foo_ptr;
...
};
and then
struct foo *array = malloc(sizeof(struct foo)*10);
bar_arr[i]->foo_ptr = array;
In this case you could write
bar_arr[i]->foo_ptr[j] = new_struct;
and
struct foo* one_ptr = bar_arr[i]->foo_ptr + j;
or
struct foo* one_ptr = &bar_arr[i]->foo_ptr[j];
This is wrong:
struct foo array* = malloc(sizeof(foo)*10);
bar_arr[i]->foo_ptr = &array;
Assuming you mean
struct foo *array = malloc(sizeof(foo)*10);
bar_arr[i]->foo_ptr = &array;
you are storing the address of the actual array variable into your structure's foo_ptr variable. From the code snippet you posted, that's likely a local variable for the function, so it's not only the wrong type, it ceases to exist once your function returns.
Given struct foo, this will allocate a pointer to an array of struct foo:
struct foo *array = malloc( nelem * sizeof( *array ) );
and this will assign that
bar_arr[i]->foo_ptr = array;
Or, more directly:
bar_arr[i]->foo_ptr = malloc( nelem * sizeof( *( bar_arr[i]->foo_ptr ) ) );
Note that I use a dereference to the pointer the malloc() result is being assigned to as the argument to sizeof(). That's a simple way to ensure that the pointer and the memory allocation done always refer to the same type.
The call to malloc() will allocate nelem contiguous copies of struct foo (which will contain unknown, unspecified data...). Those copies can be accessed via
array[ n ]
as long as n >= 0 and n < nelem.
Is it simply not possible to create a pointer to one of the elements of the structure array?
You're making your code too complex. To create a pointer to the nth element:
struct foo *nthElement = array + n;
You simply add n to the address of the first element, and the resulting pointer will refer to the nth element, assuming n is within the proper range.
Short answer
The declaration of foo_ptr in struct bar is not right. Change it into struct foo *foo_ptr. And change your assigning statement to the follows
struct foo *array = malloc(sizeof(struct foo)*10);
bar_arr[i]->foo_ptr = array;
Then you can read or write the element of the array like below
// read from array
struct foo one_struct = bar_arr[i]->foo_ptr[j];
// write to array
struct foo new_struct = { ... }
bar_arr[i]->foo_ptr[j] = new_struct;
(NOTE: the both read and write operation are copy of all fields of the struct foo).
Explanation of the changes
Think about an easy example. How do you make an array of 10 char.
char *a = malloc(sizeof(char)*10)
a is a pointer of char, it points to a space that contains 10 char. So we can use it as an array. a[4] means the 5th char of the array of 10 char.
What if you want to assign this array to another variable?
char *b = a;
Now b is an array too (not a copy of the original array, b and a point to one array). You can refer to the element via b now, just like what you do with a. E.g., b[4].
Nobody will declare b as char (*b)[] right?
More explanation of your mistakes
Still start with an simple example. When we see such a declaration -- char (*x)[10] -- what would we say about x? We may say x is a pointer to an array of 10 char.
Let's look at your declaration, struct foo (*foo_ptr)[]. Likewise, we may say, foo_ptr is a pointer to an array of ... length-unspecified struct foo. (Notice the difference in the length of array. Actually it is wrong not to specify the length, I'll talk about it soon)
Based on this declaration of yours, let's talk about the errors you encountered when using it.
Statement 1 that throws error
struct foo* one_ptr = (*bar_arr[i]->foo_ptr)[j];
To simplify and make it clear, I'm going to remove the part of bar_arr[i]-> in following discussion.
In this statement, *foo_ptr is an array of length-unspecified struct foo, we can call it this way, *foo_ptr is an array of struct foo []. So (*foo_ptr)[j] means the jth element of the array of struct foo []. Everything seems good here. BUT your array has no length defined, even though you assigned a malloc'ed array to it, but in compile-time, gcc has no idea about it. That is why it throws an error about "unspecified bounds".
Statement 2 that throws error
struct foo* one_ptr = bar_arr[i]->foo_ptr[j];
As I said above, foo_ptr is a pointer to an array of struct foo []. Let's pay attention to the fact that foo_ptr is a pointer first. So in this statement, foo_ptr[j] is kinda like *foo_ptr. Other than the index j, they have same type. Since we already know *foo_ptr is an array of struct foo [], foo_ptr[j] is also an array of struct foo []. It's an array, not an object of struct foo. To put it precisely, you need to imagine there is a big array, of which each element is still array (array of struct foo []). foo_ptr[j] is just the jth element, or say jth array, in this big array.
So the practice you assign foo_ptr[j] to one_ptr is more or less like the following example
typedef char char_array_of_4_t[4];
char_array_of_4_t array1;
char *p = array1; //ERROR: incompatible types
To make it easy to understand, I show you another exmaple below.
char array2[4];
char *p = array2;
In the second example, there is no error. In perspective of human being, array1 and array2 are both array of 4 char, however, in mind of gcc, array1 is a type of array, while array2 is a type of pointer.
In this declaration ...
struct bar{
// ...
struct foo (*foo_ptr)[];
// ...
};
... member foo_ptr of struct bar is declared as a pointer to an unknown-length array of struct foo. This is allowed, but it is unusual. One would ordinarily just declare a pointer to the first element of the array, as this plays out more naturally in C, and it's simpler, too:
struct bar{
// ...
struct foo *foo_ptr;
// ...
};
You can assign to the members of the pointed-to array via this form:
bar_arr[i]->foo_ptr[j] = new_struct;
(provided of course, that the pointed-to array has at least j + 1 elements. To get a pointer to such an element, you would do either
struct foo *struct_ptr = &bar_arr[i]->foo_ptr[j];
or, equivalently,
struct foo *struct_ptr = bar_arr[i]->foo_ptr + j;
You can do the same with your original struct declaration, but the form would need to be slightly different. For example:
struct foo *struct_ptr = &(*bar_arr[i]->foo_ptr)[j];
But really, make it easier on everybody, yourself included, and don't do that.

Why a structure is allowed to have "pointer to its own type" as member but not "(an array of the) structure type" itself?

when i try to declare the following function
typedef struct TRIE_NODE
{
char* word;
struct TRIE_NODE node[26];
}TRIE_NODE;
I get the following error:
definition of 'struct TRIE_NODE' is not complete until the closing '}'
However, if i declare this function with a pointer to the 26 nodes, it compiles just fine.
typedef struct TRIE_NODE
{
char* word;
struct TRIE_NODE* node[26];
}TRIE_NODE;
I imagine that, since this is not an instance, it's impossible for me to get a pointer to the first of those 26 arrays, but if that is the problem, how is TRIE_NODE* node[26] not also a problem? Isn't this declaration equivalent to TRIE_NODE node[1][26]?
when i try to declare the following function
Wait!! that's not a function, that's typedef-ing a structure, a user-defined type.
That said, in the first case,
typedef struct TRIE_NODE
{
char* word;
struct TRIE_NODE node[26]; //array of type struct TRIE_NODE
}TRIE_NODE;
if this has to be possible, compiler needs to know the size of the struct TRIE_NODE before it has been defined, which is impossible. So it is invalid.
On th other hand,
typedef struct TRIE_NODE
{
char* word;
struct TRIE_NODE* node[26]; //array of pointers (of type struct TRIE_NODE)
}TRIE_NODE;
is fine, as you're allocating (array of) pointers to the structure, the actual size of the structure is not required to be known by compiler at that point. So, the compiler happily allocates the pointers and the definition (construct) is perfectly valid.
To answer your own question, ask: how many bytes will
struct TRIE_NODE node[26];
occupy? In fact, what would you expect sizeof(struct TRIE_NODE) to be?
The reason
struct TRIE_NODE *node[26];
works is that we know the value of sizeof(struct TRIE_NODE*). Because all struct pointers have the same size, we can allocate an array of N struct pointers, no matter their type, even if incompletely defined.
aren't pointers and arrays almost interchangeable?
The syntax for pointers and arrays is similar. You can subscript a pointer, and you can add to an array's address. But they define different things. Basically: an array holds data, and a pointer holds an address.
In certain parts of the C standard library, you'll find structures defined like this:
struct S {
int len;
char data[1];
};
You might be tempted to ask why not use a pointer?
struct Z {
int len;
char *data;
};
Answer: struct S is actually bigger than the 5 or so bytes it seems to occupy, and the data portion begins immediately after len. In the putative struct Z example, data doesn't begin the data; the data would be somewhere else, wherever data points.
Assuming the structures are appropriate initialized, in both cases data[0] will address the first byte of the array. They're syntactically similar. But the memory layout is different. In the S case, that byte will be pretty close to (char*)&len + sizeof(len). In the Z case it will be wherever data points.
Nobody mention this, but if struct was allowed to have member or array of itself (not a pointer, but regular member or array), then the struct would be recursive and with infinite size, because the member will have one more member inside of same type and so on until infinity.

Change address of struct in C

Let's say that I was given a struct and I need to assign all of it's attributes to a particular address. The code below is giving me a conditional error, but i'm not trying to evaluate it.
struct header block_o_data;
block_o_data.a = 1;
block_o_data.b = 2;
void* startingAddress = sbrk(0);
&block_o_data = *address;
Please let me know what im doing wrong.
In the assignment to block_o_data, you're taking its address and trying to assign a value to it. The address of a variable is not an lvalue, meaning the expression cannot appear on the left side of an assignment.
You need to declare a pointer to a struct, then assign it the address of where the values actually live:
struct header *block_o_data;
void* startingAddress = sbrk(0);
block_o_data = startingAddress;
Suppose you have a struct like this:
struct mystruct {
int a;
char b;
};
then you probably need something like this:
// A pointer variable supposed to point to an instance of the struct
struct mystruct *pointer;
// This is a general address represented by void*
void *addr = some_function(0);
// Cast that general address to a pointer varibale pointing to
// an instance of the struct
pointer = (struct mystruct *) addr;
// Use it!
printf("%d", pointer->a);

Location of the struct when only the location of a member is given

Let us assume there is a struct with multiple members. The struct members are initialized with some values. The memory location of a specific member is given. Assume that you don't know the other members, their types, the ordering of members etc. Is there a way to know the memory location of the struct itself?
Is this problem called a specific name?
If you know the name of the struct, simply use offsetof
struct my_struct {
const char *name;
struct list_node list;
};
int main() {
struct my_struct t;
struct list_node* pl = &t.list;
size_t offset = offsetof(struct my_struct, list); //here
struct my_struct* pt = (struct my_struct*)((unsigned char*)pl-offset); //and here
}
If offsetof is not viable for what you're doing, then no, there's no other way. Offsetof can alternatively be written in standard C, but there's absolutely no good reason to do that.
If you know the structure type, then all you need is an offset of the field within the structure, subtract it from the member address and typecast result to pointer to the structure. For a practical implementation see FreeBSD's implementation of __containerof().
Hi Everyone I found the answer this
Cast a null pointer to the struct. You can get the offset by casting the resulting address(Offset) to a char*
(char *)(&((struct *)0)->member))
You could do any type*. But char* guarantees it's always the word size.
This should be how offsetof() is written as well

Pointer to Two Dimensional Structure Array

I have a Structure say MyStruct:-
#define SEC_DIMENSION 2
struct MyStruct
{
char cChar;
float fFloat;
int iInt;
};
struct MyStruct StructArray[SEC_DIMENSION][20]; //Two Dimensional Array of Structures.
Now I want to access this with Pointer.
struct MyStruct *StructPtr[SEC_DIMENSION];
I did assignment as follows:-
StructPtr[0] = &StructArray[0][0];
Now, I want to access Members of Structure StructArray[0][1] i.e. StructArray[0][1].cChar or StructArray[0][1].fFloat
How can I access them by using StructPtr?
I tried using StuctPtr[0][1]->cChar then ((StructPtr[0])[1])->cChar
Both returned an error.
With StructPtr[0]->cChar build was successful. But this is not what I want.
"Now I want to access this with Pointer" is not very descriptive. What you have in your example will not work. What you declared is not a pointer to an array but rather an array of pointers. Is that what you need? I don't know.
If you really need a pointer to an array, you can declare your pointer it as
struct MyStruct (*StructPtr)[20];
and then make it point to your array as
StructPtr = StructArray;
From this point on you can access the original array through this pointer as StructPtr[i][j]
StructPtr[i][j].cChar = 'a';
Alternatively, you can declare the pointer as
struct MyStruct (*StructPtr)[SEC_DIMENSION][20];
and then make it point to your array as
StructPtr = &StructArray;
From this point on you can access the original array through this pointer as (*StructPtr)[i][j]
(*StructPtr)[i][j].cChar = 'a';
I think you need a "pointer to an array of dimension [SEC_DIMENSION][20] of structures of type struct MyStruct":
struct MyStruct (*StructPtr)[SEC_DIMENSION][20];
StructPtr = StructArray;
StructPtr[i][j]->cChar;

Resources