C struct type confusing - c

struct payload{
struct metadata meta;
char data_pointer[0];
};
struct payload* mypayload = (struct payload*) malloc(sizeof(struct payload) + 50);
What is the type of mypayload here?
The address, pointer, or something else

malloc returns an untyped chunk of memory, and the assignment is how you tell the compiler what type it is. In this case struct payload * which is a pointer (an address) of the memory that was allocated or NULL if the allocation failed.
You don't need the cast (struct payload*).
If you want data_pointer to be a flexible array member, then you leave the size unspecified char data_pointer[];. An array of size 0 is undefined behavior.

What is the type of mypayload here?
mypayload is a pointer, a pointer to a struct payload. #kaylum
A struct array member with size 0, like char data_pointer[0]; is not defined by C although some implementations had allowed it as a pre-cursor to a flexible array member (FAM).
Since C99 use char data_pointer[]; to define the last member as a flexible array member.
To best allocate for a flexible array member, compute the sum of 2 sizes:
sizeof mypayload[0]: Size of the object up to, but not including the FAM member. This will include any padding before the FAM member.
sizeof mypayload->data_pointer[0]: Size of the FAM referenced data times the count, 50, of array elements desired.
Tip: a type is not needed in the sizeof code. Easier to code right, review and maintain to use the size of the referenced object.
Tip: Cast not needed.
Tip: Check for allocation success.
Example:
struct payload{
struct metadata meta;
char data_pointer[]; // No 0
};
struct payload* mypayload = malloc(
sizeof mypayload[0] +
sizeof mypayload->data_pointer[0] * 50);
if (mypayload == NULL) {
; // TBD code to handle out-of-memory
}

mypayload is a pointer. It's a pointer to the memory allocated by malloc(). And you have it configured as a pointer to a payload.

Related

How do we create an array of structure, which has the flexible array as its last field?

Let's say we have:
struct A {
int i;
char c[1];
};
Usually I would use malloc() to create an instance of A, like:
#define LEN 10
struct A *my_A = malloc(sizeof(A) + LEN * sizeof(char));
But this would not work if I try to create an array of A
A struct with a flexible array member cannot be a member of an array. This is explicitly stated in section 6.7.2.1p3 of the C standard:
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.
What you would need to do instead is declare the struct with a pointer instead of a flexible array member, and allocate space for each instance.
For example:
struct A {
int i;
char *c;
};
struct A arr[100];
for (int i=0; i<100; i++) {
arr[i].c = malloc(LEN);
}
We don't.
One of the key characteristics of an array is that you know the offset between one element and the next, and you can't do that if the elements are variably-sized.
What you can create is an array of pointers to your flexibly-sized type. How each of the pointed-to objects is allocated is up to you.
It is possible to do what you have shown in your code just using a custom allocation / array iteration mechanism (you won't be able to use the default [] operator, though, because it determines the offset based on the size of the member), but I think that you don't want to do that.
In C/C++, a "flexible" array is just a pointer to an allocated piece of memory in the heap. What you would want to do in this case is this:
struct A {
int i;
char* c; // A pointer to an array
};
#define LEN 10
#define FLEX_ARRAY_LEN 20
struct A* my_A = malloc(sizeof(A) * LEN);
// initialize each array member
for (int i = 0; i < LEN; ++i) {
// allocating new memory chunk for the flexible array of ith member
my_A[i].c = malloc(sizeof(char) * FLEX_ARRAY_LEN);
}

How to allocate memory dynamically for a struct [duplicate]

I have looked around but have been unable to find a solution to what must be a well asked question.
Here is the code I have:
#include <stdlib.h>
struct my_struct {
int n;
char s[]
};
int main()
{
struct my_struct ms;
ms.s = malloc(sizeof(char*)*50);
}
and here is the error gcc gives me:
error: invalid use of flexible array member
I can get it to compile if i declare the declaration of s inside the struct to be
char* s
and this is probably a superior implementation (pointer arithmetic is faster than arrays, yes?)
but I thought in c a declaration of
char s[]
is the same as
char* s
The way you have it written now , used to be called the "struct hack", until C99 blessed it as a "flexible array member". The reason you're getting an error (probably anyway) is that it needs to be followed by a semicolon:
#include <stdlib.h>
struct my_struct {
int n;
char s[];
};
When you allocate space for this, you want to allocate the size of the struct plus the amount of space you want for the array:
struct my_struct *s = malloc(sizeof(struct my_struct) + 50);
In this case, the flexible array member is an array of char, and sizeof(char)==1, so you don't need to multiply by its size, but just like any other malloc you'd need to if it was an array of some other type:
struct dyn_array {
int size;
int data[];
};
struct dyn_array* my_array = malloc(sizeof(struct dyn_array) + 100 * sizeof(int));
Edit: This gives a different result from changing the member to a pointer. In that case, you (normally) need two separate allocations, one for the struct itself, and one for the "extra" data to be pointed to by the pointer. Using a flexible array member you can allocate all the data in a single block.
You need to decide what it is you are trying to do first.
If you want to have a struct with a pointer to an [independent] array inside, you have to declare it as
struct my_struct {
int n;
char *s;
};
In this case you can create the actual struct object in any way you please (like an automatic variable, for example)
struct my_struct ms;
and then allocate the memory for the array independently
ms.s = malloc(50 * sizeof *ms.s);
In fact, there's no general need to allocate the array memory dynamically
struct my_struct ms;
char s[50];
ms.s = s;
It all depends on what kind of lifetime you need from these objects. If your struct is automatic, then in most cases the array would also be automatic. If the struct object owns the array memory, there's simply no point in doing otherwise. If the struct itself is dynamic, then the array should also normally be dynamic.
Note that in this case you have two independent memory blocks: the struct and the array.
A completely different approach would be to use the "struct hack" idiom. In this case the array becomes an integral part of the struct. Both reside in a single block of memory. In C99 the struct would be declared as
struct my_struct {
int n;
char s[];
};
and to create an object you'd have to allocate the whole thing dynamically
struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
The size of memory block in this case is calculated to accommodate the struct members and the trailing array of run-time size.
Note that in this case you have no option to create such struct objects as static or automatic objects. Structs with flexible array members at the end can only be allocated dynamically in C.
Your assumption about pointer aritmetics being faster then arrays is absolutely incorrect. Arrays work through pointer arithmetics by definition, so they are basically the same. Moreover, a genuine array (not decayed to a pointer) is generally a bit faster than a pointer object. Pointer value has to be read from memory, while the array's location in memory is "known" (or "calculated") from the array object itself.
The use of an array of unspecified size is only allowed at the end of a structure, and only works in some compilers. It is a non-standard compiler extension. (Although I think I remember C++0x will be allowing this.)
The array will not be a separate allocation for from the structure though. So you need to allocate all of my_struct, not just the array part.
What I do is simply give the array a small but non-zero size. Usually 4 for character arrays and 2 for wchar_t arrays to preserve 32 bit alignment.
Then you can take the declared size of the array into account, when you do the allocating. I often don't on the theory that the slop is smaller than the granularity that the heap manager works in in any case.
Also, I think you should not be using sizeof(char*) in your allocation.
This is what I would do.
struct my_struct {
int nAllocated;
char s[4]; // waste 32 bits to guarantee alignment and room for a null-terminator
};
int main()
{
struct my_struct * pms;
int cb = sizeof(*pms) + sizeof(pms->s[0])*50;
pms = (struct my_struct*) malloc(cb);
pms->nAllocated = (cb - sizoef(*pms) + sizeof(pms->s)) / sizeof(pms->s[0]);
}
I suspect the compiler doesn't know how much space it will need to allocate for s[], should you choose to declare an automatic variable with it.
I concur with what Ben said, declare your struct
struct my_struct {
int n;
char s[1];
};
Also, to clarify his comment about storage, declaring char *s won't put the struct on the stack (since it is dynamically allocated) and allocate s in the heap, what it will do is interpret the first sizeof(char *) bytes of your array as a pointer, so you won't be operating on the data you think you are, and probably will be fatal.
It is vital to remember that although the operations on pointers and arrays may be implemented the same way, they are not the same thing.
Arrays will resolve to pointers, and here you must define s as char *s. The struct basically is a container, and must (IIRC) be fixed size, so having a dynamically sized array inside of it simply isn't possible. Since you're mallocing the memory anyway, this shouldn't make any difference in what you're after.
Basically you're saying, s will indicate a memory location. Note that you can still access this later using notation like s[0].
pointer arithmetic is faster than arrays, yes?
Not at all - they're actually the same. arrays translate to pointer arithmetics at compile-time.
char test[100];
test[40] = 12;
// translates to: (test now indicates the starting address of the array)
*(test+40) = 12;
Working code of storing array inside a structure in a c, and how to store value in the array elements Please leave comment if you have any doubts, i will clarify at my best
Structure Define:
struct process{
int process_id;
int tau;
double alpha;
int* process_time;
};
Memory Allocation for process structure:
struct process* process_mem_aloc = (struct process*) malloc(temp_number_of_process * sizeof(struct process));
Looping through multiple process and for each process updating process_time dyanamic array
int process_count = 0;
int tick_count = 0;
while(process_count < number_of_process){
//Memory allocation for each array of the process, will be containting size equal to number_of_ticks: can hold any value
(process_mem_aloc + process_count)->process_time = (int*) malloc(number_of_ticks* sizeof(int));
reading data from line by line from a file, storing into process_time array and then printing it from the stored value, next while loop is inside the process while loop
while(tick_count < number_of_ticks){
fgets(line, LINE_LENGTH, file);
*((process_mem_aloc + process_count)->process_time + tick_count) = convertToInteger(line);;
printf("tick_count : %d , number_of_ticks %d\n",tick_count,*((process_mem_aloc + process_count)->process_time + tick_count));
tick_count++;
}
tick_count = 0;
the code generated will be identical (array and ptr). Apart from the fact that the array one wont compile that is
and BTW - do it c++ and use vector

typedef, arrays and pointers in C

I am studying a code written in C language.
The following part isn't clear for me:
typedef uint8_t data_t[4][4];
typedef struct {
data_t *data;
...
} my_struct;
The thing that I don't understand is, what is the type of data?
Plus, I want to assign values to this variable.
For example, in the code there is:
my_struct st;
st.data = (int8_t *)array
where array is defined as int8_t *array.
I don't understand how this assignation works, could someone explain it clearly?
To finish, is it possible to assign values to my data_t variable without declaring it as a pointer in my structure?
The thing that I don't understand is, what is the type of data?
The type of data is a pointer to a two-dimensional array. That is uint8_t(*data)[4][4].
See C right-left rule for deciphering C declarations.
Plus, I want to assign values to this variable st.data = (int8_t *)array.
In this case array must have the same layout as uint8_t[4][4] array. Since arrays are contiguous in C, that array must have at least 4 * 4 elements of type int8_t.
The fact that you have to cast the array with (uint8_t*) first implies that array has a different type and that may cause trouble.
Note that this is a pointer assignment only, not an element-wise copy of array.
is it possible to assign values to my data_t variable without declaring it as a pointer in my structure?
It is possible if data is not a pointer, i.e. declare it as data_t data;. And then copy into it using memcpy.
This declaration
typedef uint8_t data_t[4][4];
declares name data_t as an alias for type uint8_t [4][4].
Thus in the structure definition
typedef struct {
data_t *data;
...
} my_struct;
member data is a pointer of type data_t * that is the same as uint8_t ( * )[4][4].
So it is a pointer to a two-dimensional array of pointers to objects of type `uint8_t
Arrays do not have the assignment operator. You have to copy elements of one array into another.
If for example you have another one-dimensional array of pointers like
uint8_t *array[4];
you could write
my_struct st;
st.data = malloc( sizeof( data_t ) );
memcpy( st.( *data )[0], array, 4 * sizeof( uint8_t * ) );
Take into account that as the data is a pointer you have at first to allocate memory where you are going to copy objects of type uint8_t *.

how to use malloc on a pointer correctly?

I have the following struct and tried to use malloc to create a new object dynamically. It seems to work now with object_ptr obj_ptr1 = malloc(sizeof(object_ptr)); This only assigns the pointer size of object_ptr to obj_ptr1 ? but how do you assign the size of the original struct _object_t in this case?
typedef struct
{
int struct_id;
void *(*function)(void *);
int status;
} _object_t;
typedef struct _object_t* object_ptr;
/* create a new object */
object_ptr obj_ptr1 = malloc(sizeof(object_ptr));
Typedefs for pointer types are often a bad idea, since they can make it difficult to tell whether a type name refers to a pointer type or not.
Suggestion:
typedef struct { /* ... */ } object_t;
object_t *obj1 = malloc(sizeof *obj1);
And if you want to allocate space for an array of N objects:
object_t *obj1 = malloc(N * sizeof *obj1);
Note that I've removed the leading underscore from the type name. Identifiers starting with underscores are reserved to the implementation; you shouldn't define them in your own code.
The malloc(sizeof *foo) idiom may take a little getting used to, but it means you don't have to specify the type name more than once, which avoids errors. (The *obj1 doesn't actually dereference obj1, since the operand of sizeof is not evaluated.)
In your code:
object_t obj1 = malloc(sizeof(object_t));
since object_t is a pointer type, you're allocating enough memory to hold a pointer object, not a structure object. (Using such similar names object_t and _object_t for the pointer and struct types, respectively, undoubtedly contributed to the confusion.)
The problem is in your malloc line. You must allocate sizeof(_object_t) not sizeof(object_t)

initialize array inside struct in C

struct myStruct
{
short int myarr[1000];//want to initialize all elements to 0
}
How do I initialize the array?
I tried doing short int* myarr[1000]={0} inside the struct but it's wrong. How can I do this? I don't mind doing it in the implementation file. This struct is contained in a header file.
Use the universal initializer: {0}.
The universal initializer works for anything and initializes the elements to the proper 0 (NULL for pointers, 0 for ints, 0.0 for doubles, ...):
struct myStruct example1 = {0};
struct myStruct example2[42] = {0};
struct myStruct *example3 = {0};
Edit for dynamically allocated objects.
If you're allocating memory dynamically use calloc rather than malloc.
p = malloc(nelems * sizeof *p); /* uninitialized objects; p[2] is indeterminate */
q = calloc(nelems, sizeof *q); /* initialized to zero; q[2] is all zeros */
With realloc (and possibly other situations) you need to memset.
If it is declared out of a function (not on the stack), the whole struct will be zeroed at compile time.
Otherwise, you can use memset after declaring it.
Just initialize an instance of the struct with {0}, this will zero your array as well. Alternatively, use memset as NKCSS demonstrates.
int's arn't reference types, don't they get initialized after allocating memory for your structure?
You could just do this:
memset(&myStruct, 0, sizeof(myStruct));

Resources