How to make a pointer struct member behave like an array? - c

I have a pointer in my struct.
typedef struct AnotherStructure
{
int member1;
} AnotherStructure;
typedef struct Structure
{
int member1;
AnotherStructure* member2;
} Structure;
AnotherStructure x = {0};
This pointer should not behave like a normal pointer but instead should behave like an array. Now I have another piece of code,
Structure some_struct = {10, {&x, NULL /* Sentinel */}};
This doesn't work. I know why. It's because it's trying to initialize a pointer but fails to do so because the first element is neither a pointer nor an address and because we're providing it multiple initializers. But I also tried,
AnotherStructure* array[] = {&x, NULL};
Structure some_struct = {10, array};
This also doesn't work because there are different indirections (AnotherStructure** to AnotherStructure*).
Now I can't actually change the main structure. What I can do is provide different inputs to the Structure initialization. Is there way to do that?

You can use a compound literal:
Structure some_struct = {10, (AnotherStructure []) { {20}, {30} }};
and also:
AnotherStructure x[] = { {20}, {30} };
Structure some_struct = {10, x};
The syntax (type) { list of initial values } creates an object. In the case above, it creates an array of AnotherStructure, and that array is automatically converted to a pointer, which is suitable for initializing the member2 member. (Since each element of the array is a structure, the initial values for the member inside the structure are enclosed in braces.)
When used outside any function, the object will be static; its lifetime will last the duration of program execution. Inside a function, it will have automatic storage duration. Its lifetime will end when execution of its associated block ends.

You could do this:
long x = 20, y = 30;
long array[] = {x, y};
Structure some_struct = {10, array};
You just need to make sure that some_struct.member2 is not dereferenced after the lifetime of array ends (i.e. after array goes out of scope).

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.

Initializing array within structure with another array

I'm writing code in C that initializes a bunch of structures using parts of other structures. For example:
//Original structure
struct
{
int foo1;
int foo2;
int foo3;
} orig_struct = {1,2,3};
//New structure
struct
{
int bar1;
int bar2;
} new_struct = {orig_struct.foo1, orig_struct.foo2};
I have to do this for a lot of structures, and the initialization method above makes the code look very clean and readable. To be clear, I don't have any control over the original structures. I'm just creating the new structures to capture data from them.
I ran into an issue when one of the structures had a large array:
//Original structure
struct
{
int foo1;
int foo2[50];
int foo3;
} orig_struct = {1,{2,3,etc},52}; //<--replace "etc" with 48 more int values
//New structure
struct
{
int bar1;
int bar2[50];
} new_struct = {orig_struct.foo1, XXX};
Is there anything I can replace XXX with to initialize the array in the new structure with the values in the array of the original structure? Again, I'd like to keep a clean, consistent look to my code, so keeping it within the curly brackets would be ideal. I know I can manually type out each element of the array within their own curly brackets:
...
} new_struct = {orig_struct.foo1, {orig_struct.foo2[0],orig_struct.foo2[1],orig_struct.foo2[2],orig_struct.foo2[3],etc}
But it's pretty obvious why that can quickly become untenable.
Note that your syntax for initializing new_struct does not work if new_struct has static storage duration, since a constant expression is required in that case.
There really isn't any way to directly assign an array to another array. This is only allowed if the array itself is encapsulated by a structure, and you are using structure assignment. Since your original structure and new structure share a common initial prefix, you could try to exploit this through a union:
struct orig_struct_type orig_struct = {1,{2,3},52};
void some_function ()
{
union {
struct orig_struct_type o;
struct new_struct_type n;
} *u = (void *)&orig_struct;
struct new_struct_type new_struct = u->n;
/* ... */
}
If you are simply trying to reduce code duplication, you can place the array initializer list into a macro.
#define VALUES {2,3,etc} //<--replace "etc" with 48 more int
//Original structure
struct
{
int foo1;
int foo2[50];
int foo3;
} orig_struct = {1,VALUES,52};
void some_function ()
{
struct
{
int bar1;
int bar2[50];
} new_struct = {orig_struct.foo1, VALUES};
/* ... */
}
In c, I see no way to do this within an initializer, as assigning an array is not supported, and expressions must be constant expressions; so a loop or memcpy is not possible during initialization (cf. array initialization reference):
As with all other initialization, every expression in the initializer
list must be a constant expression when initializing arrays of static
or thread-local storage duration:
Later on, of course, you could write memcpy(new_struct.bar2, orig_struct.foo2, sizeof(new_struct.bar2)), but this code is then separated from the struct/variable declaration.

Initialising values for memory after dynamic allocation?

Im aware that malloc() returns a pointer to the initialised block of memory, but initialising this memory is difficult for me.
struct state{
int one;
int two;
};
struct state *one = malloc(sizeof(struct state));
*one = (struct state){.one = 10,.two = 20};
free(one);
Im aware that the above thing can be done to initialise a bunch of values for the structure without individually accessing the fields and changing the value manually.But can anyone explain how the above code works?
Also how can I do this for a pointer to several ints. The code below doesn't seem to work:
int *pointer = (int*) {1,2,3,4,5};
can anyone explain how the above code works?
In the same way that the code below works:
int *one = malloc(sizeof(int));
*one = 1020;
free(one);
The only difference is that instead of assigning a numeric value your code assigns the value of the struct, expressed through a struct aggregate. Everything else is the same: the assignment copies the content of one region of memory into another region of memory.
Also how can i do this for a pointer to several ints?
Use memcpy, like this:
int *pointer = malloc(5*sizeof(int));
static int data[] {1, 2, 3, 4, 5};
memcpy(pointer, data, sizeof(data));
free(pointer);
But can anyone explain how the above code works?
I can explain what it means.
struct state{
int one;
int two;
};
That declares a structure type with tag state, which thereafter can be referenced via the type name struct state.
struct state *one = malloc(sizeof(struct state));
That declares one as a pointer to an object of type struct state. Supposing that the malloc() succeeds, it initializes one to point to a dynamically-allocated, uninitialized block of memory exactly the size of a struct state and aligned in a manner suitable for an object of that (or any other) type.
*one = (struct state){.one = 10,.two = 20};
The right-hand side of that expression is a compound literal of type struct state. The part inside the braces is its initialization list, exactly as you might use to initialize an ordinary variable of the same type:
struct state two = { .one = 10, .two = 20 };
The .one and .two name the member initialized by each individual initializer; they are optional in this particular case because in their absence, the initializer expressions would be matched to structure members in the order the members appear in the structure type declaration. Overall, the statement copies the value of the literal struct to the object pointed-to by one.
free(one);
That releases the dynamic memory block.
Also how can i do this for a pointer to several ints[?]
There is no such thing as a pointer to several ints. There is a pointer to one int, or a pointer to specific-size array of ints, but -- and I know I'm being pedantic here -- neither of those is "a pointer to several ints".
It looks like what you want in this case is an array, not (directly) a pointer. You can initialize an array and set its size in one declaration, like so:
int array[] = {1, 2, 3, 4, 5};
Afterward, you can use array in most respects as if it were a pointer to the first int in the array.
Note, however, that unlike structures, whole arrays cannot be assigned to. Although the above code may look like it contains an assignment, it does not -- it contains an initializer. Though the syntax is similar, initializers are not assignments. The latter are executable statements; the former are not.
(struct state){.one = 10,.two = 20}; is a compound literal. It is an object that remains valid until the end of the block scope.
*one = (struct state){.one = 10,.two = 20};
Is equivalent to
struct state temp = {.one = 10,.two = 20};
*one = temp;
In the second example, the definition of the compound literal is wrong, you must specify an array type, and then you point your pointer just like normal:
int *pointer = (int[]) {1,2,3,4,5};
Again this is equivalent to:
int temp[] = {1,2,3,4,5} ;
int *pointer = temp;
It's best to have a function (or macro if you're into those):
struct state{
int one;
int two;
};
struct state* alloc_state(int one, int two)
{
struct state s = {one, two}; // order is per struct definition!
struct state* p = malloc(sizeof(struct state));
memcpy(p, &s, sizeof(s));
return p;
}
This function will always stay 4 lines of code regardless of how many argument are used.
The same principle can be used with other types.
Macro version:
#define ALLOC_STATE(p, ...) \
{ \
struct state s = {__VA_ARGS__}; \
p = malloc(sizeof(struct state)); \
memcpy(p, &s, sizeof(s));\
}
Usage:
struct state* p;
ALLOC_STATE(p, 3, 4);

Can one element in struct access another element of itself in C?

I want to declare a int num in struct S. Then the same struct should also have a array B of size num(So B will access num from it's own struct).
while in a function, I can do,
func(int A)
{
int max=A; //I could use A directly, I am just trying to explain my plan.
int B[max];
}
same won't work for struct as such,
struct S {
int num;
int data[num]; //this is wrong, num is undeclared
};
Is there any way I can do this?
Use a flexible array member:
struct S {
int num;
int data[];
};
int x = 42;
struct S *p = malloc(sizeof (struct S) + sizeof (int [x]));
p->num = x;
There are several problems with
struct S {
int num;
int data[num];
};
that cause it to not work the way you want to.
The first is that the num being used in the array member declaration isn't the same num that's the member of the struct type; the compiler treats the num in the array declaration as a regular identifier (i.e., it assumes there's a different variable named num in the same scope as the struct declaration)1.
The second problem is that a struct or union type may not have a variable-length array as a member2. However, the last member in the struct may have an incomplete array type:
struct S {
int num;
int data[];
};
Unfortunately, you're still kind of stuck here; if you create an instance of struct S like
struct S foo;
it doesn't actually allocate any space for the array. You'd need to allocate the struct dynamically:
/**
* Note that sizeof doesn't try to actually dereference foo below
*/
struct S *foo = malloc( sizeof *foo + N * sizeof *foo->arr );
to allocate space for the array itself. Note that you cannot declare an array of struct S or use it as a member of another structure or union type if the last member has an incomplete array type. 3
Honestly, your best option is to define the struct as
struct S {
size_t num;
int *data;
};
and then allocate the memory for data as a separate operation from allocating memory for the struct object itself:
struct S foo;
foo.num = some_value();
foo.data = malloc( sizeof *foo.data * foo.num );
Since struct S now has a known size, you can declare arrays of it, and you can use it as a member of another struct or union type:
struct S blah[10];
struct T {
struct S s;
...
};
1. C supports four different name spaces - label names (disambiguated by label syntax), struct/union/enum tag names (disambiguated by the presence of the struct, union, or enum keyword), struct and union member names (disambiguated by the . and -> component selection operators), and everything else. Since the num in your array declaration is not an operand of . or ->, the compiler treats it as a regular variable name.
2. 6.7.2.1/9: "A member of a structure or union may have any complete object type other than a variably modified type."
2. 6.2.7.1/3: A structure or union shall not contain a member with incomplete or function type (hence,
a structure shall not contain an instance of itself, but may contain a pointer to an instance
of itself), except that the last member of a structure with more than one named member
may have incomplete array type; such a structure (and any union containing, possibly
recursively, a member that is such a structure) shall not be a member of a structure or an
element of an array.
First of all, the member num is not declared until the end of the struct definition, which ends at the last }.
Second, how would it make sense to set the array size to be the value of an uninitialized variable?
What I think you attempt to do with int B[max] is to create a variable length array (VLA). But that won't work either, as they are explicitly forbidden inside structs. 6.7.2.1/9:
A member of a structure or union may have any complete object type other than a
variably modified type.
What you could do instead is to declare a flexible array member, as demonstrated in the answer by Ouah.
The reason the compiler complains when you "flexibly declare" the array in the struct in global memory, is because global memory can only be allocated (declared) at compile-time and at compile time all sizes must be known. (The value of a variable is not known at compile time by definition.)
The reason it accepts a flexible array in a function, is because the function's local variables are created at the moment the function is entered and then the compiler can accept a variable size. (It boils down to the compiler allocating more memory on the stack and offsetting all accesses to local variables with the size - but different compilers could have a different approach.)
#include <stdio.h>
int size;
struct S {
int num;
int a[size]; // illegal: size must be known at compile time
};
int f(int size)
{
int a[size]; // legal as a is allocated on the stack
....
}
The following would be legal:
#include <stdio.h>
#define A_SIZE 10
struct S {
int num;
int a[A_SIZE]; // legal: A_SIZE is known at compile time
};
P.s.: I am not a C99 programmer; I may have some mistakes here.

How to initialize a structure with flexible array member

I have the following structure
typedef struct _person {
int age;
char sex;
char name[];
}person;
I have done some basic internet search (but unsuccessful) on how to create an instance and initialize a structure with a flexible array member without using malloc().
For example: for normal structures like
struct a {
int age;
int sex;
};
We can create an instance of struct a and initialize it like
struct a p1 = {10, 'm'};
But for structures with flexible array in it (like _person as mentioned above) how can we create an instance and initialize like how we do it for normal structures?
Is it even possible? If so, how do we pass the array size during the initialization and the actual value to be initialized?
(or)
Is it true that the only way to create a structure with flexible array is using malloc() as mentioned in C99 specification - 6.7.2.1 Structure and union specifiers - point #17?!
No, flexible arrays must always be allocated manually. But you may use calloc to initialize the flexible part and a compound literal to initialize the fixed part. I'd wrap that in an allocation inline function like this:
typedef struct person {
unsigned age;
char sex;
size_t size;
char name[];
} person;
inline
person* alloc_person(int a, char s, size_t n) {
person * ret = calloc(sizeof(person) + n, 1);
if (ret) memcpy(ret,
&(person const){ .age = a, .sex = s, .size = n},
sizeof(person));
return ret;
}
Observe that this leaves the check if the allocation succeeded to the caller.
If you don't need a size field as I included it here, a macro would even suffice. Only that it would be not possible to check the return of calloc before doing the memcpy. Under all systems that I programmed so far this will abort relatively nicely. Generally I think that return of malloc is of minor importance, but opinions vary largely on that subject.
This could perhaps (in that special case) give more opportunities to the optimizer to integrate the code in the surroundings:
#define ALLOC_PERSON(A, S, N) \
((person*)memcpy(calloc(sizeof(person) + (N), 1), \
&(person const){ .age = (A), .sex = (S) }, \
sizeof(person)))
Edit: The case that this could be better than the function is when A and S are compile time constants. In that case the compound literal, since it is const qualified, could be allocated statically and its initialization could be done at compile time. In addition, if several allocations with the same values would appear in the code the compiler would be allowed to realize only one single copy of that compound literal.
There are some tricks you can use. It depends on your particular application.
If you want to initialise a single variable, you can define a structure of the correct size:
struct {
int age;
char sex;
char name[sizeof("THE_NAME")];
} your_variable = { 55, 'M', "THE_NAME" };
The problem is that you have to use pointer casting to interpret the variable as "person"(e.g. "*(person *)(&your_variable)". But you can use a containing union to avoid this:
union {
struct { ..., char name[sizeof("THE_NAME")]; } x;
person p;
} your_var = { 55, 'M', "THE_NAME" };
so, your_var.p is of type "person".
You may also use a macro to define your initializer, so you can write the string only once:
#define INIVAR(x_, age_, sex_ ,s_) \
union {\
struct { ..., char name[sizeof(s_)]; } x;\
person p;\
} x_ = { (age_), (sex_), (s_) }
INIVAR(your_var, 55, 'M', "THE NAME");
Another problem is that this trick is not suitable to create an array of "person". The problem with arrays is that all elements must have the same size. In this case it's safer to use a const char * instead of a char[]. Or use the dynamic allocation ;)
A structure type with a flexible array member can be treated as if the flexible array member were omitted, so you can initialize the structure like this.
person p = { 10, 'x' };
However, there are no members of the flexible array allocated and any attempt to access a member of the flexible array or form a pointer to one beyond its end is invalid. The only way to create an instance of a structure with a flexible array member which actually has elements in this array is to dynamically allocate memory for it, for example with malloc.

Resources