This question already has answers here:
variably modified array at file scope in C
(4 answers)
Closed 9 years ago.
I have the following code :
int b = 10; // maximum branching
typedef struct depth * depth;
struct depth{
int number ;
depth child[b] ;//<---- Error here
};
and the following error :
variably modified ‘child’ at file scope
Try this instead:
#define MAX_BRANCHING 10
int b = MAX_BRANCHING; // maximum branching
typedef struct depth * depth;
struct depth{
int number ;
depth child[MAX_BRANCHING] ;//<---- Error here
};
"Variable length arrays" (VLAs) were introduced in C99 and C11, but their use is "conditional" (compilers are not required to implement the feature). In C++, the preferred technique is to use "const int". In C, I would recommend using a #define. IMHO...
http://en.wikipedia.org/wiki/Variable-length_array
If b can't be constant, and you don't want to use heap allocation for the child array, you can use this, rather peculiar workaround (hint: consider NOT using this, but using heap allocation for the array):
typedef struct depth *depth_p;
struct depth
{
int number;
depth_p child[0];
};
The trick is, that the following statement is still valid:
depth_p d = get_depth();
d->child[5]; // <-- this is still valid
In order to use this, you need to create instances of depth_p in this (and only this) way:
depth_p create_depth(int num_children)
{
return (depth_p)malloc(
sizeof(struct depth) + num_children * sizeof(depth_p)
);
}
Firstly, this allocates memory for all the other members (int number) with sizeof(struct depth). Then, it allocates additional memory for the required amount of children by adding num_children * sizeof(depth_p).
Don't forget to free your depth references with free.
Sructs can't have dynamic members so try const int b = 10;
Related
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
I have multiple flexible arrays in s struct in c:
typedef struct
{
int a;
float b;
} Name;
typedef struct
{
int c;
int d;
int e;
} NIM;
typedef struct
{
int age;
int time;
Name name[1];
NIM nim[1];
} EthgenSig;
if we have need to allocate memory like this:
malloc(sizeof(EthgenSig) + sizeof(Name) * 10);
how the memory will be allocated and if we operator name array first and then we operate nim array later, then the nim[1] will overwrite the name array, then how to solve it?
You can't have more than one flexible-array member for the exact reason you pointed out.
At most, if you need your data to be kept all in the same memory block, you can make name and nim pointers and set where they point to the correct locations after allocation (making sure not to break any alignment constraint), but the simplest (and most sensible) thing is to just allocate separately the arrays for name and nim.
This is not so hard to do... the key is to realize that arrays and pointers in C both have very similar properties. In fact, array accessor notation has a direct correspondence to pointer notation:
a[b] == *(a + b);
Note that this has the effect of making the name of the array and the index interchangeable, so this is also true:
a[b] == b[a];
You can use this to achieve the result you want. First, declare a structure with two pointer elements. This provides two pointers that will store the base address of the two arrays:
struct two_blocks {
int *x;
int *y;
}
When you allocate this structure, you'll need to allocate extra space for the bodies of the two arrays:
#define X_SIZE 3
#define Y_SIZE 4
two_blocks *data = (two_blocks *)malloc(sizeof(two_blocks)
+ (sizeof(int) * X_SIZE)
+ (sizeof(int) * Y_SIZE));
And then the final step is to initialize the two array pointers. (These expressions use a lot of pointer type casting to ensure that the pointer arithmetic is done in single bytes. Pointer arithmetic is usually done in units of the size of the object being pointed to, to support the array/pointer equivalence I mentioned above.)
data->x = (int *)(((char *)data) + sizeof(two_blocks));
data->y = (int *)(((char *)data) + sizeof(two_blocks) + X_SIZE * sizeof(int));
From there, the arrays can be used like you'd expect:
data->x[2] = 42;
data->x[2] = 42;
A couple observations
Like Matteo said, be careful with alignment. Using this technique is taking memory layout over from the compiler, which can cause unexpected problems. If this caveat makes no sense to you, then you probably shouldn't use this technique.
One of the rationales for using this technique is that it can simplify memory management by reducing the number of frees you need to manage. If you know that your two arrays, x and y, both have the same lifecycle as their enclosing structure, then this removes one potential type of memory leak. (As well as reduces the chance of memory fragmentation by reducing the number of memory blocks.)
Having an array of size 1 is the same as not having an array at all when it comes to the memory layout of this struct.
You may as well have this:
typedef struct
{
int age;
int time;
Name name;
NIM nim;
} EthgenSig;
But I'm assuming that is not what you want. It is pretty hard to tell what you actually want. But I'm assuming that you actually want this:
typedef struct
{
int age;
int time;
Name* name;
NIM* nim;
} EthgenSig;
foo = malloc(sizeof(EthgenSig);
foo.name = malloc(sizeof(Name)*10);
foo.nim = malloc(sizeof(Nim) * 10);
I have the following code:
typedef struct
{
int name;
int info[1];
} Data;
then I have five variables:
int a, b, c, d, e;
how can I use this as a flexible array to keep all the values of the five variables?
To do this properly, you should declare the flexible array member as an incomplete type:
typedef struct
{
int name;
int info[];
} Data;
Then allocate memory for it dynamically with
Data* data = malloc(sizeof(Data) + sizeof(int[N]));
for(int i=0; i<N; i++)
{
data->info[i] = something; // now use it just as any other array
}
EDIT
Ensure that you are using a C99 compiler for this to work, otherwise you will encounter various problems:
If you allocate an array of length 1, then you will malloc 1 item for the first element of the array together with the struct, and then append N bytes after that. Meaning you are actually allocating N+1 bytes. This is perhaps not what one intended to do, and it makes things needlessly complicated.
(To solve the above problem, GCC had a pre-C99 extension that allowed zero-length arrays, which isn't allowed in standard C.)
Pre-C99, or in any other context than as a flexible array member, C doesn't allow incomplete array types as the one shown in my code.
C99 guarantees that your program is well-defined when using a flexible array member. If you don't use C99, then the compiler might append "struct padding" bytes between the other struct members and the array at the end. Meaning that data->info[0] could point at a struct padding byte and not at the first item in your allocated array. This can cause all kinds of weird, unexpected behavior.
This is why flexible array members were called "struct hack" before C99. They weren't reliable, just a dirty hack which may or may not work.
That kind of structure is a somewhat common idiom in C; the idea is that you allocate extra space at the end of the struct, where the elements of info after the first are actually stored. The size-1 array member at the end of the struct then allows you to use array syntax to access this data.
If you want to store 5 elements you'll have to do:
Data * data=malloc(sizeof(Data)+sizeof(int)*4); /* 4 because the first element is
already included in the size of
the struct */
/* error checking omitted ... */
data->info[0]=a;
data->info[1]=b;
data->info[2]=c;
data->info[3]=d;
data->info[4]=e;
/* ... */
/* when you don't need d anymore remember to deallocate */
free(data);
You may also write a helper function to ease the allocation:
Data * AllocateData(size_t elements)
{
if(elements==0)
return NULL;
return malloc(sizeof(Data)+sizeof(int)*(elements-1));
}
and the example above would be
Data * data=AllocateData(5);
/* then as above */
This is called flexible arrays and was introduced in C99. Often called a struct hack too.
In C99, the flexible array member should be declared without a size.
You need to dynamically allocate memory that can hold more memory than the size of the struct.
As the array is the last member in the struct, you can index it past its size, provided you allocated enough memory for it.
typedef struct
{
int name;
int info[1];
} Data;
Data *d = malloc(sizeof(*d) + (5 * sizeof(int)); //enough for the struct and 5 more ints.
//we have enough room for 6 elements in the info array now
//since the struct has room for 1 element, and we allocated room for another 5 ints
d->info[0] = 1;
d->info[1] = 2;
d->info[2] = 3;
d->info[3] = 4;
d->info[4] = 5;
d->info[5] = 6;
Using an array member with 1 size int info[1]; in this manner is technically undefined behavior - but will work fine on many popular compilers. With a C99 compiler this is supported by a flexible array member declared as int info[];. Read more here
Hi I have the following scenario
#define CONSTANT 10
struct structA{
int var1;
int var2[CONSTANT];
};
main(){
structA *varA = NULL;
int i;
/* some C code */
varA = mmap(0,..);
for(i = 0; i < CONSTANT; i++){
varA.var2[i] = /* C code */ ;
}
/* C code */
}
Here the number of elements in var2 array of structA is constant and hence the varA.var2[i] can be directly referenced . But If the number CONSTANT is to be determined dynamically during runtime , how should the structure definition be modified?
The cleanest way would be to use a C99 flexible array member:
struct structA{
int var1;
int var2[];
};
Then you can just mmap(NULL, sizeof(int) * (num + 1), ...). Just be careful with flexible array members, sizeof behaves funny with them (doesn't include their size).
If you can't / won't use a flexible array member, you can use a pointer instead of an array and mmap memory separately for it.
The most common way to do this is:
struct structA{
int var1;
int var2[1];
};
It's not really an array with a single element, because you allocate more memory than the size of a structA.
The number CONSTANT cannot be determined dynamically at runtime, since it affects the structure size.
The usual trick for what you're trying to do (I'm not sure if it's strictly valid C but it's very common) is to create
struct structA{
int var1;
int var2[0];
};
and when you map or allocate, allocate (sizeof(structA) + sizeof(int) * CONSTANT) bytes.
I declared a Normal Structure In C:
typedef struct arr_struct{
int* original;
int size;
int first[size/2];
int second[size-(size/2)];
};
when compile it gives me:
test.c:11: error: ‘size’ undeclared here (not in a function)
any explanation?
You can't define arrays based on a variable size. The size has to be known at compile time. You'll need to make first and second pointers and dynamically allocate them once size is known.
You're getting the error message because you're trying to use the size member of the struct illegally. For one thing, the struct type definition isn't complete until the closing }, so until then the compiler doesn't know that there's a size member within the struct. For another, you cannot refer to a struct member without a struct instance; when you used the expression size the declarators for first and second, the compiler was looking for a variable named size outside of the struct definition.
It is possible to use a VLA within a struct type, but that's really not the approach you want to take here if you're doing what I think you're doing. Better to make first and second pointers to int and allocate them as necessary (as demonstrated by a couple of the answers above).
int val;
scanf("%d",&val);
int a[val];
The above code actually compiles and runs in my gcc compiler.
The reason for not working inside a struct could be due to the lining up of elements inside a struct whose size can't be determined at compile time. I am not fully sure about it though.
An implementation and usage for what miked said could be (without error checking):
typedef struct
{
int size;
int* first;
int* second;
} arr_struct;
// Prepare an arr_struct for use.
arr_struct foo;
foo.size = 1337;
foo.first = malloc(sizeof(int)*foo.size);
foo.second = malloc(sizeof(int)*(foo.size-foo.size/2));
Do remember to free(foo.first) and free(foo.second) when you're done, though!
The size you provide for an array needs to be a constant expression. You have a couple of choices. One would be to include a couple of pointers, and allocate the space dynamically:
typedef struct {
int* original;
int size;
int *first;
int *second;
} arr_struct;
Another possibility would be to use only one array, and create a pointer to the proper point in it:
typedef struct {
int* original;
int size;
int *second;
int first[];
} arr_struct;
This uses a flexible array member, which is new with C99 -- if you're using an out of date C compiler (e.g., MS VC++) it might not be supported directly1. In any case, this still requires dynamic allocation, but lets you do one large allocation for all the data instead of three separate allocations (one for the struct, and one each for first and second).
arr_struct *my_struct = malloc(sizeof(*my_struct) + size * sizeof(int));
my_struct->second = my_struct->first + size/2;
As an aside, note the syntax for typedef -- as it was, your typedef wasn't defining a name at all.
1The workaround is trivial though -- just define first with a size of 1 and subtract 1 from size in your allocation:
arr_struct *my_struct = malloc(sizeof(*my_struct) + (size-1) * sizeof(int));
In theory, this isn't required to work, but in fact it's just fine with all real compilers, at least AFAIK.