I'm trying to allow a variable length array inside a struct in a C program. Something like this:
struct result{
int column;
int row;
const char* a[var][var];
};
how do i do this?
even the following definition would do:
struct result{
int column;
int row;
const char* a[row][column];
};
plese do help...
You can't have variable size arrays in C structs.
You can have pointers to arrays which can be variable size (you need to handle the allocation of the space separately), but you are declaring arrays of pointers instead
If you want an array of pointers, try
const char (*a)[][];
(you'll need to manage the array as an array of pointers to arrays if you want both dimensions to be variable)
Just use pointers instead. You'll have to do dynamic memory allocation. Don't forget to free() the memory allocated for your array :)
P.S.: If you need a 2-dimensional array, use a pointer-to-pointer (that is, allocate memory for an array of pointers)
For single-dimension arrays you can do something like this:
struct TEST {
...
int size;
char string[];
}
where the size field indicates how many characters there are in the string array. The array has to be the last member of the struct, and you have to allocate the struct's memory dynamically. The allocated size should be sizeof(struct TEST) + size * sizeof(char) in this case.
You cannot have more than one variable size array in the struct. Multi-dimension variable-size arrays are trickier. It cannot be done unless only one dimension size is unknown, specifically that of the first dimension.
struct TEST {
...
int size;
char string[][100];
}
EDIT:
As other posters mentioned, you can have pointers to one or more arrays, at the cost of having to manage their memory areas separately from the struct.
EDIT 2:
This is part of at least the ISO C99 standard. Shamelessly copying from paragraph 6.7.2.1, sub-paragraph 16:
16 As a special case, the last element
of a structure with more than one
named member may have an incomplete
array type; this is called a flexible
array member. With two exceptions,
the flexible array member is ignored.
First, the size of the structure shall
be equal to the offset of the last
element of an otherwise identical
structure that replaces the flexible
array member with an array of
unspecified length.106)...
Use dynamic allocation with the malloc function.
In your case you should do something like:
#include <stdlib.h> /* header file for the malloc function */
void allocateResult(struct result* res, int row, int column) {
res->a = (const char*) malloc(row * column * sizeof(char));
}
Please note that sizeof(char) equals to 1 (almost all the time), but for other types you'd have to do it this way.
This solution implies to free allocated memory before the program ends. You'll have to pass the pointer in your struct to free:
void freeResult(struct result* res) {
free(res->a);
}
Related
(corrected the code after a few good comments pointing out some mistakes in the previous version of the code)
If I'm right, the best way to dynamically allocate a 2D array of structs in C is the following:
struct xx(*array2d)[y] = malloc(sizeof(struct xx[x][y]));
Does it make any difference whether I store the structs in the array or store pointers to them?
I was also wondering if I may simply deallocate the allocated memory in the following way:
void free2d(int x, int y, struct xx array2d[x][y]) {
free(array2d);
}
Identifiers in C cannot begin with numbers so 2darray won't work.
Formally, the most correct way to allocated a 2D array dynamically is:
struct xx (*array)[x][y] = malloc(sizeof(struct xx[x][y]));
However that makes accessing the array cumbersome, because we would have to de-reference the array pointer first:
(*array)[i][j]
A common trick to avoid this is to have the array pointer not point at the "whole" 2D array, but to the first item. Which would be a struct xx [y] array in this case.
So we can use a pointer to the first element but still allocate the correct amount:
struct xx (*array)[y] = malloc(sizeof(struct xx[x][y]));
And now we can use this as
array[i][j]
In either of the two examples above, you free it with a single free(array) call.
The allocation code is a bit incorrect.
variable name cannot start with a digit, thus identifier 2darray is illegal. Use array2d instead
memory allocation code look almost correct. Note that array2d would be a pointer to array of x elements of type struct xx. Thus the correct allocation code swap order of x and y in sizeof expression.
struct xx (*array2d)[x] = malloc(sizeof(struct xx[y][x]));
If you want x be the first dimensions use:
struct xx (*array2d)[y] = malloc(sizeof(struct xx[x][y]));
Personally I prefer to use the following pattern because it is less error prone:
struct xx (*array2d)[x] = calloc(y, sizeof *array2d);
Passing to function. It is simple, just pass array dimensions as arguments and then the array itself.
void foo(int x, int y, struct xx array2d[static x][y]) {
Note that parameter array2d is actually a pointer to array. The "static extent" tells the compiler that at least x elements pointer by the pointer are valid. It is very useful for documentation. Moreover static makes the declaration visually distinct from a declaration of an array.
Deallocation. The free2d function could be used if it followed the pattern from point 2. However I recommend simply using free(array2d);
I would use objects instead of types.
struct xx(*array2d)[cols] = malloc(rows *sizeof(*array2D));
To deallocate you do not need sizes only void pointer to your array
void free2d(void *array2d) {
free(array2d);
}
or simple use free with your pointer to the array.
This question already has answers here:
What is the cause of flexible array member not at end of struct error?
(3 answers)
Closed 2 years ago.
A struct like this works:
struct a {
char b;
int array[];
};
But if I put char b; after int array[]; like this:
struct a {
int array[];
char b;
};
it gives me an error, more specifically "struct 'a' has an illegal zero-sized array".
Why do I get this error only when the order is reversed?
The C standard says only the last member of a structure can be a flexible array, and a fundamental reason for this is that no member can be assigned a position after a flexible array because the size of the flexible array is not known.
Memory is provided for a flexible array member by allocating memory for the base size of the structure plus additional memory for the array members. The amount of this additional memory is not known to the compiler while translating the program, so it has no way of knowing where members after the array would be located. So it could not compose a structure with such members.
Normally arrays needs to have a size, in structures the size must even be a compile-time constant (variable-length arrays are not possible in structures).
But there is an exception: Flexible array members, which is what the first structure is using. A structure can only have one single flexible array member, and it must always placed as the last member of the structure.
C allows an array of unspecified size as the last member of a struct. This is referred to as a flexible array member.
You can make use of this by dynamically allocating memory for the struct plus however many array elements you want for the last member. For example:
struct a *my_a = malloc(sizeof(*my_a) + 5 * sizeof(int));
This allocates space for an instance of struct a with 5 members for array.
If any member other than the last one has an unspecified array size it is considered a syntax error.
I have a function that is supposed to be creating structures and storing them in an array of structures.
Lets say this is my structure:
struct str {
...
};
The function takes a parameter that looks like this:
struct str **ptr
Which is a pointer to a pointer that points to a structure if I get it right and I am supposed to set this parameter to be pointing to the first element of the array of structures which will be the first structure in that array.
So, if the parameter looks like this, that means that instead of having just an array of structures, I have an array of pointers that point to that structure, right?
Now I have declared the array of pointers to structures like this:
struct str *structures[20];
because I am expecting to have 20 (pointers to )structures store there.
Then I have a loop that is allocating memory for the structures and is storing them in the array like this:
struct str *structure;
structure = malloc(sizeof(struct str));
Then I fill in the parameters of the structure I want like this:
structure->a = 1; structure->b = 2; .........
And I store it in the array like this:
structures[n] = structure;
And I make sure it is stored in the array at the position where I wanted it to be by printing a parameter from the structure each loop like this:
printf("%d\n", structures[7]->a);
My question is, how do I set the parameter of the function to be pointing to the first pointer to a structure in that array?
And did I get it right?
Also, the parameter needs to be taken from main.
And I need to work with these (pointers to)structures of the array outside this one function as well.
What will the parameter look like?
struct str *pointer; ?
Also, wouldn't it be possible to just point the pointer to the array itself and it should automatically be pointing to the first element in it?
So that I could then reference the nth member of the array via the pointer since I need to work with all of them later on?
I have looked at this thread, but I'm still a bit confused so I'd appreciate any feedback.
Reading through this, I notice a few inconsistencies in your post:
Why create an array of pointers to your struct as opposed to a simple array of structs? That is, let's say you have this declaration for your struct:
struct myStruct {
int x;
int y;
};
If you want to create an array of those structs just do:
//dynamic
struct myStruct* myArray = malloc(20*sizeof(struct myStruct));
//static
struct myStruct* myArray[20];
Note that both of these return a pointer to the first element of the array (which is of type struct myStruct). Your array is an array of struct myStruct elements, not an array of struct myStruct*.
An array of struct myStruct elements with size 20 is, for practical purposes, nothing more than contiguous memory big enough to hold 20 struct myStruct elements and represented by the pointer to the first element. Since the memory is contiguous, you can access the 'nth' element of your array by myArray[0] or *(myArray+n) (the latter is possible because an "array" is nothing more than a pointer to the first element of contiguous memory... so "adding" 1 to a pointer of a given type gives you the memory address of the next element... which you deference using the * operator to get the element itself).
It'll be much easier (not to mention much faster) to allocate memory for your array of structs once rather than creating an array of pointers to your structs. And then modify them in place.
So a function that takes in the array and increments that 5th and 6th elements might look like:
void modifyStructs (struct myStruct* myArray)
{
//modify the fifth struct:
++myArray[4].x;
//modify the sixth struct:
++myArray[5].x;
}
The few times you'll want an array of pointers are when:
Creating a multidimensional array. Even then, this is really bad for cache performance... it's better to create a 1D array and define a macro for how to access the elements. BLAS/LAPACK do this.
Creating an array where some elements should be NULL and you're not using structs. If you're using structs, it's much better to just define a field to identify whether your struct has been populated yet and use a simple array of structs.
Creating an array to access a huge number of items but you don't want to allocate all that memory yet. Here, you don't really have a choice.
Is there any way to find the structure size dynamically in C??
Sizeof is compile time operator.. so what's the other option.
If we can have dynamically allocated array(flexible arrays) in a structure, then finding the structure size dynamically should also be there.. Plz help me out...
When you allocate an array dynamically in C, then you must remember its size too, if you wish to know the size of the array!
Structure sizes must be known at compile-time.
If it contains a pointer to dynamically allocated memory then that memory is not part of the struct - it's outside the struct and the pointer is pointing at it - so it does not affect the sizeof the struct.
If you're talking about flexible array member then you will need to implement your own way of knowing how much memory you allocated, e.g. have a struct member variable that holds the size.
sizeof's results are compile time constant as a the size of a variable or structure does not change during run-time.
The only exception to this are V(ariable)L(ength)Arrays for which the code defnding them "knows" the size.
Referring:
we can have dynamically allocated array in a structure
So let's assume:
struct s
{
size_t size;
int * ints;
}
The size is sizeof(struct s). That is the sum of
the size of an unsigned interger: sizeof(size_t)
the size of a pointer to int: sizeof (int *)
some optional padding bytes
This is independed of to how many bytes the structure's member int * ints may point.
There is a struct like this:
struct sdshdr {
int len;
int free;
char buf[];
};
And the result of printf ("%d\n", sizeof(struct sdshdr));is 8. If I change char buf[] to char *, the result would be 16. Why is char buf[] taking no space here(sizeof(int) is 4)? When shoud I choose char buf[] over char *buf?
The construct with the empty brackets [] is allowed as the last element of the struct. It lets you allocate additional space beyond sizeof(sdshdr) for the elements of the array, letting you embed the array data with the array itself.
Pointers, on the other hand, store the data in a separately managed segment of memory, and require an additional call to free at the end. Unlike the [] way, pointers let you have more than one variable-length array inside the same struct, and the element can be placed anywhere in the struct, not only at the end of the struct.
Taking "char[]" more generally:
char[] will actually allocate a number of characters inside the struct. (A struct with char x[17] will grow by 17 bytes and so on.) A char* will just hold a pointer.
An actual char x[] (with no size specified - and I think the same goes for size 0) at the end of the struct is a special case called a "flexible array member" and is discussed in the linked question and in the other answer.
Remember also that sizeof needs to be determined at compile time. Since char buf[] is a flexible array member it's size cannot be known at compile time, therefore will be omitted from the calculation of sizeof.
char * is a pointer to a char variable, and it's size is known so is included (however that is the size of the pointer not the array it points to).