tags:

views:

73

answers:

5

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?

+4  A: 

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.

miked
Actually you can have arrays based on a variable size, but it appears that it doesn't apply inside a struct.
Gunner
in gcc it works
Aboelnour
Yeah I remember something in C99 about variable size arrays. But the last time I did any pure C (not C++) programming, I was on a non-compliant compiler so I never used them in practice.
miked
You can only have an array of indeterminate size as the last member of a structure (flexible array member) in C99. And since only one can be the last, you can only have one such flexible array member. You also can't use them in arrays, or in other structures.
Jonathan Leffler
Guys, the error message has **nothing to do** with using a VLA in a struct and everything to do with trying to use the `size` member incorrectly.
John Bode
+1  A: 
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.

Gunner
A: 

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!

gspr
i did this solution but I was asking for an explanation thanks :)
Aboelnour
A: 

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.

Jerry Coffin
That's not a VLA, that's an *incomplete* array type. There's a difference.
John Bode
@John Bode: well, half right anyway. Thanks for drawing my attention to the slip -- I've edited in the correct term.
Jerry Coffin
+1  A: 

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).

John Bode