My Struct looks like this:
typedef struct storage {
char ***data;
int lost_index[];
int lost_index_size;
int size;
int allowed_memory_key_size;
int allowed_memory_value_size;
int memory_size;
int allowed_memory_size;
} STORAGE;
The error im getting is «error: flexible array member not at end of struct». Im aware that this error can be solved by moving int lost_index[]
at the end of struct. Why should flexible array member need to be at the end of struct? What is reason?
As this is assumed duplicate of another question, actually i didn’t find answers that i actually needed, answers in similar question dont describe the reason which stands behind compiler to throw error i asked about.
Thanks
asked May 11, 2016 at 13:36
5
Unlike array declarations in function parameters, array declared as part of a struct
or a union
must have a size specified (with one exception described below). That is why declaring
int lost_index[];
int lost_index_size;
is incorrect.
The exception to this rule is so-called «flexible array member», which is an array declared with no size at the end of the struct
. You must place it at the end of the struct
so that the memory for it could be allocated along with the struct
itself. This is the only way the compiler could know the offsets of all data members.
If the compiler were to allow flexible arrays in the middle of a struct
, the location of members starting with size
, allowed_memory_key_size
, and on, would be dependent on the amount of memory that you allocate to lost_index[]
array. Moreover, the compiler would not be able to pad the struct
where necessary to ensure proper memory access.
answered May 11, 2016 at 13:42
0
No10 30 / 28 / 4 Регистрация: 03.06.2010 Сообщений: 465 |
||||||||
1 |
||||||||
25.07.2013, 12:27. Показов 4248. Ответов 5 Метки нет (Все метки)
Вот такой код:
Ошибка вот такого содержания:
Почему? В Чем проблема?
__________________
0 |
Псевдослучайный 1946 / 1145 / 98 Регистрация: 13.09.2011 Сообщений: 3,215 |
|
25.07.2013, 14:19 |
2 |
А чего вы ожидали? Какого размера должен был получиться массив и, соответственно, по какому смещению компилятор должен разместить следующие поле?
0 |
Модератор 11660 / 7173 / 1704 Регистрация: 25.07.2009 Сообщений: 13,144 |
|
25.07.2013, 14:45 |
3 |
Хотя если бы такое объявление было в конце структуры, то о размере query можно было бы позаботиться вручную при выделении памяти. Какой-то подозрительный манёвр… А sizeof(struct q_query) что возвращать должен?
0 |
Модератор 33885 / 18911 / 3982 Регистрация: 12.02.2012 Сообщений: 31,716 Записей в блоге: 13 |
|
25.07.2013, 15:17 |
4 |
«flexible array member not at end of struct» — дословно означает, что динамический массив следует размещать последним элементом структуры.
0 |
NoMasters Псевдослучайный 1946 / 1145 / 98 Регистрация: 13.09.2011 Сообщений: 3,215 |
||||
25.07.2013, 16:00 |
5 |
|||
Решениеeasybudda, размер без учёта динамического массива.
1 |
easybudda Модератор 11660 / 7173 / 1704 Регистрация: 25.07.2009 Сообщений: 13,144 |
||||
25.07.2013, 16:36 |
6 |
|||
РешениеNoMasters, ну да, наверное, но конструкция всё равно опасная. Тогда нужно в самой структуре держать размер массива (ну это как бы само собой), главное по запарке не написать
Самый надёжный, но кондовый и расточительный метод — держать в структуре массив максимально допустимого размера. Правда, если массив большой, а объектов структуры много — снова беда…
0 |
- Forum
- General Programming Boards
- C Programming
- flexible array member not at end of struct
-
05-05-2004
#1
Lode Runner
flexible array member not at end of struct
in a struct, I would have an array of size [][3], where [] is undefined. But it won’t work :
example
Code:
struct foo { int bar[][3]; };
I get :
Code:
11: error: flexible array member not at end of struct
I can’t use cause then I have bar[3][].
Anyone ?… Anyone ?
-
05-05-2004
#2
End Of Line
The size of the array must be known at compile time. So, either go with a fixed array size:
int foo[10][3];
or go with an array of pointers and malloc the memory later on.When all else fails, read the instructions.
If you’re posting code, use code tags: [code] /* insert code here */ [/code]
-
05-05-2004
#3
Lode Runner
OK, so what would the malloc line look like ?
Code:
myFoo.bar=malloc(3*size*sizeof(int));
or should I make two mallocs (one for *(myFoo.bar) and one for myFoo.bar) ? though I don’t know how to write the first one.
pointers and memory management are still fuzzy to me
-
05-06-2004
#4
Lode Runner
OK, I’m advancing here. I have my struct now like this
Code:
struct foo { int **bar; int **bar2; }
and it works in most cases.
the problem is I want to use a foo as a global variable. But I can’t if I don’t give the entries to the struct. and bar2 is not easy stuff. I have a big function to calculate bar2’s entries. I can’t just write them down.
Any ideas on how to handle this ?
-
05-06-2004
#5
Ultraviolence Connoisseur
You want to make a variable of type struct foo, global or foo itself? just declare it outside of any functions (and above them)
-
05-06-2004
#6
End Of Line
When all else fails, read the instructions.
If you’re posting code, use code tags: [code] /* insert code here */ [/code]
-
05-06-2004
#7
and the hat of int overfl
Which compiler are you using?
Code:
struct foo { int a; int bar[][3]; };
compiles it just fine with
gcc -std=c99 prog.cBear in mind that it is wrong to have a struct consisting only of a flexible array
Commenting out the int a; causes gcc to report
flexible array member in otherwise empty struct
-
05-14-2004
#8
Lode Runner
I toyed around for a while with what you guys told me, understood some important I am sillyI am sillyI am sillyI am silly, learned a few tricks, and finally, when I thought everything was going to work I have some new stupid problems.
first of all :
compiles it just fine with
gcc -std=c99 prog.cdoesn’t work, I get the same goddamn errors. I guess it the BSD kernel or something, security issues maybe.
Next, i still have my struct but this time I’m trying to mallocate it.
Code:
struct foo { int **bar; }
Everything compiles nicely with this, but when I try to declare a foo type global variable in the main program with this line :
Code:
struct foo *myFoo = malloc(12*sizeof(int));
I get :
Code:
error: initializer element is not constant
I put (12*sizeof(int)) thinking of bar being 4×3…
-
05-14-2004
#9
Registered User
>error: initializer element is not constant
You can’t call malloc outside of a function. Global initializers must be constant.When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.
-
05-14-2004
#10
Yes, my avatar is stolen
I think this is what you’re trying to do:
Code:
#include <stdlib.h> #include <stdio.h> struct foo { int (* bar)[3]; /* Declares a pointer to an int array[3] */ }; struct foo myFoo; int main(void) { int i, j; int k = 0; /* Allocate memory for myFoo.bar */ myFoo.bar = malloc(4 * sizeof(*myFoo.bar)); /* Check success of memory allocation */ if (myFoo.bar == NULL) { fprintf(stderr, "Out of memoryn"); return EXIT_FAILURE; } /* Sample usage of myFoo.bar */ for (i = 0;i < 4;i++) for (j = 0;j < 3;j++) myFoo.bar[i][j] = k++; for (i = 0;i < 4;i++) for (j = 0;j < 3;j++) printf("myFoo.bar[%d][%d] = %dn", i, j, myFoo.bar[i][j]); /* Use myFoo in the rest of your program as needed. */ getchar(); return EXIT_SUCCESS; }
Note especially the method of declaring a pointer to an int array[3]. This is covered in more detail in «Chapter 8: Pointers to Arrays» at the site Hammer linked to.
Last edited by anonytmouse; 05-14-2004 at 06:48 AM.
-
05-14-2004
#11
Lode Runner
YES ! PERFECT ! THANK YOU !
I guess you guys spent a whole lot of time coding in C
I’ve got to get used to thinking like this.
Well, thanks a lot everyone.
-
05-14-2004
#12
Lode Runner
not so perfect,
I can only fill the first row of bar. when I start putting some stuff in myFoo.bar[1][0], I get a Bus Error.
Can anyone explain ?
actually your code works but mine (the real one, not the example) doesn’t. I’ll check this a little further.
Last edited by krappa; 05-14-2004 at 11:09 AM.
-
05-14-2004
#13
Lode Runner
I’d changed the .c but not the .h
Some days I really loathe myself.
-
05-14-2004
#14
and the hat of int overfl
I dunno if this is what you’re trying to do — you keep changing between arrays and pointers.
Code:
#include <stdio.h> #include <stdlib.h> #include <string.h> struct foo { char name[20]; // 20 int a; // 4 int bar[][3]; // 12*n }; int main() { struct foo *jobber; size_t alloc; int i, j; printf( "%un", sizeof *jobber ); printf( "%un", sizeof jobber->a ); printf( "%un", sizeof jobber->bar[0] ); // put a bar[10][3] at the end of the structure alloc = sizeof *jobber + sizeof jobber->bar[0] * 10; printf( "allocating %u bytesn", alloc ); jobber = malloc( alloc ); strcpy( jobber->name, "hello" ); jobber->a = 123; for ( i = 0 ; i < 10 ; i++ ) { for ( j = 0 ; j < 3 ; j++ ) { jobber->bar[i][j] = i * j; } } return 0; }
Popular pages
- Exactly how to get started with C++ (or C) today
- C Tutorial
- C++ Tutorial
- 5 ways you can learn to program faster
- The 5 Most Common Problems New Programmers Face
- How to set up a compiler
- 8 Common programming Mistakes
- What is C++11?
- Creating a game, from start to finish
Recent additions
- How to create a shared library on Linux with GCC — December 30, 2011
- Enum classes and nullptr in C++11 — November 27, 2011
- Learn about The Hash Table — November 20, 2011
- Rvalue References and Move Semantics in C++11 — November 13, 2011
- C and C++ for Java Programmers — November 5, 2011
- A Gentle Introduction to C++ IO Streams — October 10, 2011
Similar Threads
-
Replies: 10
Last Post: 10-09-2006, 10:36 AM
-
Replies: 20
Last Post: 06-27-2006, 12:13 AM
-
Dikumud
By maxorator in forum C++ Programming
Replies: 1
Last Post: 10-01-2005, 06:39 AM
-
Replies: 3
Last Post: 09-11-2005, 12:19 PM
-
Replies: 6
Last Post: 04-17-2005, 07:10 AM
Example
C99
Type Declaration
A structure with at least one member may additionally contain a single array member of unspecified length at the end of the structure. This is called a flexible array member:
struct ex1
{
size_t foo;
int flex[];
};
struct ex2_header
{
int foo;
char bar;
};
struct ex2
{
struct ex2_header hdr;
int flex[];
};
/* Merged ex2_header and ex2 structures. */
struct ex3
{
int foo;
char bar;
int flex[];
};
Effects on Size and Padding
A flexible array member is treated as having no size when calculating the size of a structure, though padding between that member and the previous member of the structure may still exist:
/* Prints "8,8" on my machine, so there is no padding. */
printf("%zu,%zun", sizeof(size_t), sizeof(struct ex1));
/* Also prints "8,8" on my machine, so there is no padding in the ex2 structure itself. */
printf("%zu,%zun", sizeof(struct ex2_header), sizeof(struct ex2));
/* Prints "5,8" on my machine, so there are 3 bytes of padding. */
printf("%zu,%zun", sizeof(int) + sizeof(char), sizeof(struct ex3));
The flexible array member is considered to have an incomplete array type, so its size cannot be calculated using sizeof
.
Usage
You can declare and initialize an object with a structure type containing a flexible array member, but you must not attempt to initialize the flexible array member since it is treated as if it does not exist. It is forbidden to try to do this, and compile errors will result.
Similarly, you should not attempt to assign a value to any element of a flexible array member when declaring a structure in this way since there may not be enough padding at the end of the structure to allow for any objects required by the flexible array member. The compiler will not necessarily prevent you from doing this, however, so this can lead to undefined behavior.
/* invalid: cannot initialize flexible array member */
struct ex1 e1 = {1, {2, 3}};
/* invalid: hdr={foo=1, bar=2} OK, but cannot initialize flexible array member */
struct ex2 e2 = {{1, 2}, {3}};
/* valid: initialize foo=1, bar=2 members */
struct ex3 e3 = {1, 2};
e1.flex[0] = 3; /* undefined behavior, in my case */
e3.flex[0] = 2; /* undefined behavior again */
e2.flex[0] = e3.flex[0]; /* undefined behavior */
You may instead choose to use malloc
, calloc
, or realloc
to allocate the structure with extra storage and later free it, which allows you to use the flexible array member as you wish:
/* valid: allocate an object of structure type `ex1` along with an array of 2 ints */
struct ex1 *pe1 = malloc(sizeof(*pe1) + 2 * sizeof(pe1->flex[0]));
/* valid: allocate an object of structure type ex2 along with an array of 4 ints */
struct ex2 *pe2 = malloc(sizeof(struct ex2) + sizeof(int[4]));
/* valid: allocate 5 structure type ex3 objects along with an array of 3 ints per object */
struct ex3 *pe3 = malloc(5 * (sizeof(*pe3) + sizeof(int[3])));
pe1->flex[0] = 3; /* valid */
pe3[0]->flex[0] = pe1->flex[0]; /* valid */
C99
The ‘struct hack’
Flexible array members did not exist prior to C99 and are treated as errors. A common workaround is to declare an array of length 1, a technique called the ‘struct hack’:
struct ex1
{
size_t foo;
int flex[1];
};
This will affect the size of the structure, however, unlike a true flexible array member:
/* Prints "8,4,16" on my machine, signifying that there are 4 bytes of padding. */
printf("%d,%d,%dn", (int)sizeof(size_t), (int)sizeof(int[1]), (int)sizeof(struct ex1));
To use the flex
member as a flexible array member, you’d allocate it with malloc
as shown above, except that sizeof(*pe1)
(or the equivalent sizeof(struct ex1)
) would be replaced with offsetof(struct ex1, flex)
or the longer, type-agnostic expression sizeof(*pe1)-sizeof(pe1->flex)
. Alternatively, you might subtract 1 from the desired length of the «flexible» array since it’s already included in the structure size, assuming the desired length is greater than 0. The same logic may be applied to the other usage examples.
Compatibility
If compatibility with compilers that do not support flexible array members is desired, you may use a macro defined like FLEXMEMB_SIZE
below:
#if __STDC_VERSION__ < 199901L
#define FLEXMEMB_SIZE 1
#else
#define FLEXMEMB_SIZE /* nothing */
#endif
struct ex1
{
size_t foo;
int flex[FLEXMEMB_SIZE];
};
When allocating objects, you should use the offsetof(struct ex1, flex)
form to refer to the structure size (excluding the flexible array member) since it is the only expression that will remain consistent between compilers that support flexible array members and compilers that do not:
struct ex1 *pe10 = malloc(offsetof(struct ex1, flex) + n * sizeof(pe10->flex[0]));
The alternative is to use the preprocessor to conditionally subtract 1 from the specified length. Due to the increased potential for inconsistency and general human error in this form, I moved the logic into a separate function:
struct ex1 *ex1_alloc(size_t n)
{
struct ex1 tmp;
#if __STDC_VERSION__ < 199901L
if (n != 0)
n--;
#endif
return malloc(sizeof(tmp) + n * sizeof(tmp.flex[0]));
}
...
/* allocate an ex1 object with "flex" array of length 3 */
struct ex1 *pe1 = ex1_alloc(3);
View previous topic :: View next topic | |||||||||||||||
Author | Message | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Fulgurance Veteran Joined: 15 Feb 2017 |
|
||||||||||||||
Back to top |
|
||||||||||||||
GDH-gentoo Veteran Joined: 20 Jul 2019 |
|
||||||||||||||
Back to top |
|
||||||||||||||
Fulgurance Veteran Joined: 15 Feb 2017 |
|
||||||||||||||
Back to top |
|
||||||||||||||
GDH-gentoo Veteran Joined: 20 Jul 2019 |
|
||||||||||||||
Back to top |
|
||||||||||||||
Fulgurance Veteran Joined: 15 Feb 2017 |
|
||||||||||||||
Back to top |
|
||||||||||||||
GDH-gentoo Veteran Joined: 20 Jul 2019 |
|
||||||||||||||
Back to top |
|
||||||||||||||
Fulgurance Veteran Joined: 15 Feb 2017 |
|
||||||||||||||
Back to top |
|
||||||||||||||
GDH-gentoo Veteran Joined: 20 Jul 2019 |
|
||||||||||||||
Back to top |
|
||||||||||||||
Fulgurance Veteran Joined: 15 Feb 2017 |
|
||||||||||||||
Back to top |
|
||||||||||||||
Fulgurance Veteran Joined: 15 Feb 2017 |
|
||||||||||||||
Back to top |
|
||||||||||||||
GDH-gentoo Veteran Joined: 20 Jul 2019 |
|
||||||||||||||
Back to top |
|
||||||||||||||
Fulgurance Veteran Joined: 15 Feb 2017 |
|
||||||||||||||
Back to top |
|
||||||||||||||
GDH-gentoo Veteran Joined: 20 Jul 2019 |
|
||||||||||||||
Back to top |
|
||||||||||||||
Fulgurance Veteran Joined: 15 Feb 2017 |
|
||||||||||||||
Back to top |
|
||||||||||||||
GDH-gentoo Veteran Joined: 20 Jul 2019 |
|
||||||||||||||
Back to top |
|
||||||||||||||
|
You cannot post new topics in this forum |