# Why the sizeof is 4

H

#### Hill Pang

The is my code:

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof f1);
}

The output(by GCC) is 4.
My question is why it doesn't count the size of the flexible array while it is static initialized?
In other words, if I want to know the *really* size of f1, how to do it? is it possible?

J

#### Johann Klammer

Hill said:
The is my code:

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof f1);
}

The output(by GCC) is 4.
My question is why it doesn't count the size of the flexible array while it is static initialized?
In other words, if I want to know the *really* size of f1, how to do it? is it possible?

Not using sizeof alone.
You could try:

struct f1 {
int x; size_t size; int y[];
} f1 = { 1, 3, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof(f1)+sizeof(f1.y)*f1.size);
}

possibly wrap it in some #define

I doubt it is safe to use in a static declaration like this.
You may be overrunning the end...
Better do a malloc(), or declare with y[3].

I

#### Ian Collins

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()

Ditto this.

I

#### Ian Collins

The is my code:

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof f1);
}

The output(by GCC) is 4.
My question is why it doesn't count the size of the flexible array while it is static initialized?

See paragraph 17 in section 6.7.2.1 of C99 and note the example.
In other words, if I want to know the *really* size of f1, how to do it? is it possible?

No, you have to save it explicitly somewhere.

I

#### Ike Naar

printf("sizeof %d\n", sizeof(f1)+sizeof(f1.y)*f1.size);

sizeof f1.y is wrong,
you probably meant sizeof f1.y[0] or sizeof *f1.y .

Z

#### Zhang Yuan

Hill said:
The is my code:

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof f1);
}

The output(by GCC) is 4.
My question is why it doesn't count the size of the flexible array while it is static initialized?
In other words, if I want to know the *really* size of f1, how to do it? is it possible?

Not using sizeof alone.
You could try:

struct f1 {
int x; size_t size; int y[];
} f1 = { 1, 3, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof(f1)+sizeof(f1.y)*f1.size);
why sizeof(f1) become to 8;?
}

possibly wrap it in some #define

I doubt it is safe to use in a static declaration like this.
You may be overrunning the end...
Better do a malloc(), or declare with y[3].

Z

#### Zhang Yuan

Hill said:
The is my code:

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof f1);
}

The output(by GCC) is 4.
My question is why it doesn't count the size of the flexible array while it is static initialized?
In other words, if I want to know the *really* size of f1, how to do it? is it possible?

Not using sizeof alone.
You could try:

struct f1 {
int x; size_t size; int y[];
} f1 = { 1, 3, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof(f1)+sizeof(f1.y)*f1.size);
}

possibly wrap it in some #define

I doubt it is safe to use in a static declaration like this.
You may be overrunning the end...
Better do a malloc(), or declare with y[3].

Hill said:
The is my code:

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof f1);
}

The output(by GCC) is 4.
My question is why it doesn't count the size of the flexible array while it is static initialized?
In other words, if I want to know the *really* size of f1, how to do it? is it possible?

Not using sizeof alone.
You could try:

struct f1 {
int x; size_t size; int y[];
} f1 = { 1, 3, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof(f1)+sizeof(f1.y)*f1.size);
}
why sizeof(f1) changed from 4 to 8 ?
possibly wrap it in some #define

I doubt it is safe to use in a static declaration like this.
You may be overrunning the end...
Better do a malloc(), or declare with y[3].

J

#### James Kuyper

struct f1 {
int x; size_t size; int y[];
} f1 = { 1, 3, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof(f1)+sizeof(f1.y)*f1.size);
why sizeof(f1) become to 8;?

It now includes both 'x' and 'size'. It does not include y: "the size of
the structure is as if the flexible array member were omitted except
that it may have more trailing padding than the omission would imply."
(6.7.2.1p18)

J

#### Johann Klammer

Sorry, Imade a mistake. it should be: "sizeof(f1)+sizeof(f1.y[0])*f1.size"
as Ike Naar posted earlier.
why sizeof(f1) changed from 4 to 8 ?

It is now something like sizeof(int)+sizeof(size_t).
But may be more if padding is inserted by compiler.

H

#### Hill Pang

The is my code:

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof f1);
}

The output(by GCC) is 4.
My question is why it doesn't count the size of the flexible array while it is static initialized?

See paragraph 17 in section 6.7.2.1 of C99 and note the example.
In other words, if I want to know the *really* size of f1, how to do it? is it possible?

No, you have to save it explicitly somewhere.

--

Yes, C99 will ignore the flexible array member while counting the structuresize, but in C99 it also specify that the flexible array member could not be static initialized, the example shows it:
So the static initialization to flexible array member is a extension of GCC, while it is initialized statically, from my opinion, it should make senseto count the size of the flexible array member. I would suggest this as a enhancement of GCC to the great GCC developer.

J

#### Johann Klammer

Hill said:
Yes, C99 will ignore the flexible array member while counting the structure size, but in C99 it also specify that the flexible array member could not be static initialized, the example shows it:

So the static initialization to flexible array member is a extension of GCC, while it is initialized statically, from my opinion, it should make sense to count the size of the flexible array member. I would suggest this as a enhancement of GCC to the great GCC developer.

I doubt this is possible, as the sizeof is a property of the type, and
you would want it different depending on initialisation.
The fact that gcc compiles the code may be a bug. Are you sure, it
actually reserves space for the supplied values?

H

#### Hill Pang

I doubt this is possible, as the sizeof is a property of the type, and
you would want it different depending on initialisation.
The fact that gcc compiles the code may be a bug. Are you sure, it
actually reserves space for the supplied values?

Yes, I verified the space is reserved.

N

#### Noob

Hill said:
This is my code:

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof f1);
}

\$ cat flexarr.c
struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };
int main(void)
{
return sizeof f1;
}

\$ gcc -std=c99 -pedantic -Wall flexarr.c
flexarr.c:3:1: warning: initialization of a flexible array member
flexarr.c:3:1: warning: (near initialization for 'f1.y')

As an extension, "GCC allows static initialization of flexible array members."
http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

B

#### Ben Bacarisse

Noob said:
Hill said:
This is my code:

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()
{
printf("sizeof %d\n", sizeof f1);
}

\$ cat flexarr.c
struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };
int main(void)
{
return sizeof f1;
}

\$ gcc -std=c99 -pedantic -Wall flexarr.c
flexarr.c:3:1: warning: initialization of a flexible array member
flexarr.c:3:1: warning: (near initialization for 'f1.y')

As an extension, "GCC allows static initialization of flexible array members."
http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

Just to clarify... It gets it right, in that the extra data is put in
the right place (f1.y[2] == 4) but it's not considered part of the
struct. f1.y remains incomplete and the size of that of the struct
without the flexible array member (but including any padding that would
be required).

K

#### Keith Thompson

Hill Pang said:
The is my code:

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()

This should be "int main(void)".
{
printf("sizeof %d\n", sizeof f1);
}

The output(by GCC) is 4.
My question is why it doesn't count the size of the flexible array
while it is static initialized? In other words, if I want to know the
*really* size of f1, how to do it? is it possible?

Because that's the way it's defined by the language.

N1570 6.7.2.1p18:

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 . In most situations, the flexible
array member is ignored. In particular, the size of the structure
is as if the flexible array member were omitted except that it
may have more trailing padding than the omission would imply.

Yes, it would be nice if sizeof yield the full size, including however
much space is in that final array. But that would require the compiler
to keep track of how it was allocated, and to generate run-time code
when the size is not constant. It also would have required nailing down
the definition in all cases.

Flexible array members are basically a better-defined version of the
"struct hack" (see question 2.6 of the comp.lang.c FAQ,
<http://www.c-faq.com>).

If you want to keep track of how many elements are in that final array,
you'll just have to do it yourself. For example, you might add a member
that holds the current number of elements -- and make sure that its
value is correct at all times.

H

#### Hill Pang

Hill Pang
writes:
The is my code:

struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

void main()

This should be "int main(void)".
{
printf("sizeof %d\n", sizeof f1);
}

The output(by GCC) is 4.
My question is why it doesn't count the size of the flexible array
while it is static initialized? In other words, if I want to know the
*really* size of f1, how to do it? is it possible?

Because that's the way it's defined by the language.

N1570 6.7.2.1p18:

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 . In most situations, the flexible
array member is ignored. In particular, the size of the structure
is as if the flexible array member were omitted except that it
may have more trailing padding than the omission would imply.

Yes, it would be nice if sizeof yield the full size, including however
much space is in that final array. But that would require the compiler
to keep track of how it was allocated, and to generate run-time code
when the size is not constant. It also would have required nailing down
the definition in all cases.

Flexible array members are basically a better-defined version of the
"struct hack" (see question 2.6 of the comp.lang.c FAQ,
<http://www.c-faq.com>).

If you want to keep track of how many elements are in that final array,
you'll just have to do it yourself. For example, you might add a member
that holds the current number of elements -- and make sure that its
value is correct at all times.

--
Keith Thompson (The_Other_Keith) (e-mail address removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Could the allocated space be changed for a variable after it is statically initialized?

I

#### Ike Naar

Hill said:
struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };

Could the allocated space be changed for a variable after it is
statically initialized?

No, you'd have to declare a pointer to the struct type and allocate
space dynamically (using malloc or similar) if you want to be able
to resize it later (using realloc).

#include <stdlib.h>

struct f1 {
int x; int y[];
};

extern do_something(struct f1 *, int);

int main(void)
{
struct f1 *pf1 = malloc(sizeof *pf1 + 3 * sizeof pf1->y[0]);
if (pf1 != NULL)
{
pf1->x = 1;
pf1->y[0] = 2;
pf1->y[1] = 3;
pf1->y[2] = 4;
do_something(pf1, 3);
struct f1 *r = realloc(pf1, sizeof *pf1 + 4 * sizeof pf1->y[0]);
if (r != NULL)
{
pf1 = r;
pf1->y[3] = 5;
do_something(pf1, 4);
}
free(pf1);
}
return 0;
}