Structure size

J

Jim Langston

Bruce. said:
Jim Langston said:
Bruce. said:
Since you aren't worried about padding bytes the obvious answer is

typedef struct
{
int var1;
int var2;
int var3;
char var4[ 1024 - 3*sizeof(int) ];
} MYSTRUCT;

Thanks but my example was oversimplified to keep it brief. The actual
structures are much more complex, too complex for a solution like that.

I guess what I was looking for doesn't exist.

But thanks anyway.

Someone already showed you how to use it. Use a union.

#include <iostream>

typedef union
{
struct {
int v1;
int v2;
int v3;
} var;
char unused [1024];
} MyStruct;

int main(void)
{
MyStruct Foo;

std::cout << sizeof( Foo ) << "\n";

Foo.var.v1 = 10;
Foo.var.v2 = 20;
Foo.var.v3 = 30;
}

var.v1 will start at position 0.

You forgot var4. I need var4 to be sized automattically to achieve a
structure size of 1024. I need var4 to the size of the remaining space up
to 1024 bytes. In this case it would be:

struct {
int v1;
int v2;
int v3;
char v4[1024 - 12];
} var;

But I want the compiler to figure the 12 automattically.

Why do you need v4 to be the size of the remaining bytes? If it's because
you need a pointer...

typedef union
{
struct {
int v1;
int v2;
int v3;
char v4[1]
} var;
char unused [1024];
} MyStruct;

int main(void)
{
MyStruct Foo;

std::cout << sizeof( Foo ) << "\n";

Foo.var.v1 = 10;
Foo.var.v2 = 20;
Foo.var.v3 = 30;
}

Now v4 will point to the biggin of the remaining data. You already said you
would get the actual length in another variable, and that's all you need,
right? Just because v4 is only declared as having one character, you can
still use v4[1] v4[2] etc... This is acutally done all the time on accident
by programmers (buffer overrun) but in this case you actually have more
data.
 
O

Old Wolf

struct {
int v1;
int v2;
int v3;
char v4[1024 - 12];
} var;

But I want the compiler to figure the 12 automattically.

Make it:
char v4[1024 - 3 * sizeof(int)];

You can include a compile-time check that it has
figured the size correctly and hasn't added padding:
STATIC_ASSERT( sizeof var == 1024 );

where STATIC_ASSERT is a macro that causes a
compile-time error if the argument is not true.
(google for some possibilities).
 
B

Bruce.

Jim Langston said:
Now v4 will point to the biggin of the remaining data. You already said
you would get the actual length in another variable, and that's all you
need, right?

No, the size of v4 will be used to SET that dataLength value.
Just because v4 is only declared as having one character, you can still
use v4[1] v4[2] etc... This is acutally done all the time on accident by
programmers (buffer overrun) but in this case you actually have more data.

Picture this:

MYSTRUCT myStruct;
char buffer[9999];

memcpy( myStruc.v4, buffer, sizeof( myStruct.v4 ));

Without v4 being explicidly sized, my program won't know how big it is.

Bruce.
 
O

Old Wolf

Picture this:

MYSTRUCT myStruct;
char buffer[9999];

memcpy( myStruc.v4, buffer, sizeof( myStruct.v4 ));

Without v4 being explicidly sized, my program won't know how big it is.

memcpy( myStruct.v4, buffer, sizeof myStruct - offsetof(MYSTRUCT,
v4) );

But I do agree that using a 1-sized array is not
a good solution; it causes undefined behaviour
and can lead to unexpected results like the one
you mentioned.
 
J

James Dennett

Bruce. said:
Richard Heathfield said:
Bruce. said:
I would like to allocate a structure size of 1024 bytes but I want the
compiler to do the calculation for me.

typedef struct
{
int var1;
int var2;
int var3;
char var4[ ?????? ];
} MYSTRUCT;

What I want to do is replace the ?????? something that will
automattically make the total structure 1024 bytes without having to
manually count the bytes of the other members myself.

Is that possible in c++?
Not portably. Implementations may insert arbitrary padding after any
structure member. In a pathological implementation, you might have to
give var4 a negative number of elements (which is of course
impossible).

In this case, portability is not a requirement and the compiler packing is
fixed a 1. I'm using MS Developer Studio C++ 2003. Does that change your
answer at all? Thanks.

What you *can* do portably is to use 1024-3*sizeof(int) combined
with some kind of static_assert check that sizeof(MYSTRUCT)==1024.
It won't work completely portably, but if it compiles it'll work.

(The only risk is that you might not update the 3*sizeof(int) when
the struct changes, and you might move platforms to one where the
padding fills in a hole you've left, and you might not test your
code very thoroughly.)

-- James
 
K

Keith Thompson

Bruce. said:
Jim Langston said:
Bruce. said:
Since you aren't worried about padding bytes the obvious answer is

typedef struct
{
int var1;
int var2;
int var3;
char var4[ 1024 - 3*sizeof(int) ];
} MYSTRUCT;

Thanks but my example was oversimplified to keep it brief. The actual
structures are much more complex, too complex for a solution like that.

I guess what I was looking for doesn't exist.

But thanks anyway.

Someone already showed you how to use it. Use a union.

#include <iostream>

typedef union
{
struct {
int v1;
int v2;
int v3;
} var;
char unused [1024];
} MyStruct;

int main(void)
{
MyStruct Foo;

std::cout << sizeof( Foo ) << "\n";

Foo.var.v1 = 10;
Foo.var.v2 = 20;
Foo.var.v3 = 30;
}

var.v1 will start at position 0.

You forgot var4. I need var4 to be sized automattically to achieve a
structure size of 1024. I need var4 to the size of the remaining space up
to 1024 bytes. In this case it would be:

struct {
int v1;
int v2;
int v3;
char v4[1024 - 12];
} var;

But I want the compiler to figure the 12 automattically.

He didn't forget var4 (or v4), he's telling you why you don't need it.

Given:

struct data {
int v1;
int v2;
int v3;
};

union block {
struct data d;
char filler[1024];
};

union block obj;

an object of type 'union block' will have a size of exactly 1024 bytes
(as long as 'struct data' is no larger than 1024 bytes). The data
members can be referred to as 'obj.d.v1', obj.d.v3', obj.d.v3'.

By using a union, you don't have to worry about alignment issues, and
you don't have to compute the number of bytes of padding.
 

nmi

Joined
Jul 6, 2007
Messages
13
Reaction score
0
Bruce. said:
If I change it to this:

#pragma pack( 1 )

typedef struct
{
int var1;
int var2;
int var3;
char var4[ ?????? ];
} MYSTRUCT;

Now do you know of a portable way to accomplish what I want?

Bruce.

This should be portable I guess:

#pragma pack(1)

struct TheStruct {
int var1;
int var2;
int var3;
char var4[1024 - (3 * sizeof(int))];
};
 
L

LR

Bruce. said:
Jim Langston said:
Bruce. said:
Since you aren't worried about padding bytes the obvious answer is

typedef struct
{
int var1;
int var2;
int var3;
char var4[ 1024 - 3*sizeof(int) ];
} MYSTRUCT;
Thanks but my example was oversimplified to keep it brief. The actual
structures are much more complex, too complex for a solution like that.

I guess what I was looking for doesn't exist.

But thanks anyway.
Someone already showed you how to use it. Use a union.

#include <iostream>

typedef union
{
struct {
int v1;
int v2;
int v3;
} var;
char unused [1024];
} MyStruct;

int main(void)
{
MyStruct Foo;

std::cout << sizeof( Foo ) << "\n";

Foo.var.v1 = 10;
Foo.var.v2 = 20;
Foo.var.v3 = 30;
}

var.v1 will start at position 0.

You forgot var4. I need var4 to be sized automattically to achieve a
structure size of 1024. I need var4 to the size of the remaining space up
to 1024 bytes. In this case it would be:

struct {
int v1;
int v2;
int v3;
char v4[1024 - 12];
} var;

But I want the compiler to figure the 12 automattically.

I'm not sure that I follow what you mean here, but if I do, then I think
that your best bet might be to use either some very complicated
#defines, or perhaps a template. Maybe something like this:

(I'm assuming that as you said in another post, you don't have a
portability problem and you can control your compiler to take care of
packing issues.)

struct x1 {
int a,b,c;
};

struct x2 {
int a; double e,f,g,h,i;
};

template<typename T>
struct Message {
T t;
char v[1024 - sizeof(T)];
};

then, else where you can...

Message<x1> m1;
Message<x2> m2;

there will be the added annoyance of having to reference the individual
members of x1 and x2 by doing something like m1.t.a = 43; It might be
wise to pick a better name for t.

In the real world, I'd guess that I'd want to add some default ctors and
maybe some other things methods to your structs. Perhaps you'd want all
of the messages or all of the xn's to inherit from some class. I don't
know.

I'm making a few enormous assumptions about what you want to do and why,
and I'm really not sure that I follow what you're attempting or why, so
please tell me, does this help? Or do you have something else in mind?

LR
 
V

Victor Bazarov

LR said:
Bruce. said:
Jim Langston said:
Since you aren't worried about padding bytes the obvious answer is

typedef struct
{
int var1;
int var2;
int var3;
char var4[ 1024 - 3*sizeof(int) ];
} MYSTRUCT;
Thanks but my example was oversimplified to keep it brief. The
actual structures are much more complex, too complex for a
solution like that. I guess what I was looking for doesn't exist.

But thanks anyway.
Someone already showed you how to use it. Use a union.

#include <iostream>

typedef union
{
struct {
int v1;
int v2;
int v3;
} var;
char unused [1024];
} MyStruct;

int main(void)
{
MyStruct Foo;

std::cout << sizeof( Foo ) << "\n";

Foo.var.v1 = 10;
Foo.var.v2 = 20;
Foo.var.v3 = 30;
}

var.v1 will start at position 0.

You forgot var4. I need var4 to be sized automattically to achieve a
structure size of 1024. I need var4 to the size of the remaining
space up to 1024 bytes. In this case it would be:

struct {
int v1;
int v2;
int v3;
char v4[1024 - 12];
} var;

But I want the compiler to figure the 12 automattically.

I'm not sure that I follow what you mean here, but if I do, then I
think that your best bet might be to use either some very complicated
#defines, or perhaps a template. Maybe something like this:

(I'm assuming that as you said in another post, you don't have a
portability problem and you can control your compiler to take care of
packing issues.)

struct x1 {
int a,b,c;
};

struct x2 {
int a; double e,f,g,h,i;
};

template<typename T>
struct Message {
T t;
char v[1024 - sizeof(T)];
};

then, else where you can...

Message<x1> m1;
Message<x2> m2;

there will be the added annoyance of having to reference the
individual members of x1 and x2 by doing something like m1.t.a = 43;
It might be wise to pick a better name for t.

[..]

I am not sure here, but I believe there is no guarantee that the size
of the 'Message<x1>' or 'Message<x2>' is actually going to be 1024
even with the mechanism you give here. I wonder, however, if there
is something in the Standard related to the sizes (and alignments)
that I missed, and it might actually impose certain limitations thus
giving programmers more leeway when it comes to determining type sizes.

V
 
L

LR

Victor said:
LR wrote:
(I'm assuming that as you said in another post, you don't have a
portability problem and you can control your compiler to take care of
packing issues.)

struct x1 {
int a,b,c;
};

struct x2 {
int a; double e,f,g,h,i;
};

template<typename T>
struct Message {
T t;
char v[1024 - sizeof(T)];
};

then, else where you can...

Message<x1> m1;
Message<x2> m2;

[..]

I am not sure here, but I believe there is no guarantee that the size
of the 'Message<x1>' or 'Message<x2>' is actually going to be 1024
even with the mechanism you give here.

Is that because of templates? Nested structs? Are you referring to the
OP's particular compiler and it's control of packing/alignment?
> I wonder, however, if there
is something in the Standard related to the sizes (and alignments)
that I missed, and it might actually impose certain limitations thus
giving programmers more leeway when it comes to determining type sizes.

I don't know. Considering the kinds of variations that can exist
between platforms for these kinds of things like sizeof for various
types and alignment requirements, it would surprise me to find something
in the standard.

I think what might save the OP in this case is that he doesn't need a
portable result, and his compiler can, through some non-portable means
control packing.

Perhaps off topic? But I think that because the OP wanted to get this
result automagically it's still of interest.

LR
 
J

James Kanze

Bruce. said:
Richard Heathfield said:
Bruce. said:
I would like to allocate a structure size of 1024 bytes but I want the
compiler to do the calculation for me.
typedef struct
{
int var1;
int var2;
int var3;
char var4[ ?????? ];
} MYSTRUCT;
What I want to do is replace the ?????? something that will
automattically make the total structure 1024 bytes without having to
manually count the bytes of the other members myself.
Is that possible in c++?
Not portably. Implementations may insert arbitrary padding after any
structure member. In a pathological implementation, you might have to
give var4 a negative number of elements (which is of course
impossible).
In this case, portability is not a requirement and the compiler packing is
fixed a 1. I'm using MS Developer Studio C++ 2003. Does that change your
answer at all? Thanks.
What you *can* do portably is to use 1024-3*sizeof(int) combined
with some kind of static_assert check that sizeof(MYSTRUCT)==1024.
It won't work completely portably, but if it compiles it'll work.
(The only risk is that you might not update the 3*sizeof(int) when
the struct changes, and you might move platforms to one where the
padding fills in a hole you've left, and you might not test your
code very thoroughly.)

If the goal is just to have a data structure of the desired
size, something like:

union SizedStruct
{
MyStruct data ;
char dummyForSize[ 1024 ] ;
} ;

can be used. Of course, you'll now have to refer to the
elements as data.var1, etc., instead of simply var1.
 
J

James Kanze

LR said:
Bruce. said:
I would like to allocate a structure size of 1024 bytes but I want the
compiler to do the calculation for me.
typedef struct
{
int var1;
int var2;
int var3;
char var4[ ?????? ];
} MYSTRUCT;
What I want to do is replace the ?????? something that will
automattically make the total structure 1024 bytes without having to
manually count the bytes of the other members myself.
Is that possible in c++?
May I ask why you want to do that?
I'm creating a new message type, and the message buffers are
hard coded at 1024 bytes. So I need var4 to be as big as
possible but the entire structure can not exceed 1024 bytes.

If you're streaming the data, you probably can't use int
directly anyway. So just use char buffer[whatever].
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

Victor said:
LR wrote:
(I'm assuming that as you said in another post, you don't have a
portability problem and you can control your compiler to take care of
packing issues.)

struct x1 {
int a,b,c;
};

struct x2 {
int a; double e,f,g,h,i;
};

template<typename T>
struct Message {
T t;
char v[1024 - sizeof(T)];
};

then, else where you can...

Message<x1> m1;
Message<x2> m2;

[..]

I am not sure here, but I believe there is no guarantee that the size
of the 'Message<x1>' or 'Message<x2>' is actually going to be 1024
even with the mechanism you give here.

Is that because of templates? Nested structs? Are you referring to the
OP's particular compiler and it's control of packing/alignment?

The structs I would guess, there's no guarantee that there wont be any
padding between the t and v in Message.
 
J

James Kanze

LR wrote:

[...]
(I'm assuming that as you said in another post, you don't have a
portability problem and you can control your compiler to take care of
packing issues.)
struct x1 {
int a,b,c;
};
struct x2 {
int a; double e,f,g,h,i;
};
template<typename T>
struct Message {
T t;
char v[1024 - sizeof(T)];
};
then, else where you can...
Message<x1> m1;
Message<x2> m2;
there will be the added annoyance of having to reference the
individual members of x1 and x2 by doing something like m1.t.a = 43;
It might be wise to pick a better name for t.
[..]
I am not sure here, but I believe there is no guarantee that the size
of the 'Message<x1>' or 'Message<x2>' is actually going to be 1024
even with the mechanism you give here.

It's certainly not guaranteed by the standard. A compiler could
insert padding between the t and v, and still be conform. As a
quality of implementation issue... I would consider it a poor
choice on a byte addressed machine (and none of the compilers
I've ever used did insert padding here).
I wonder, however, if there
is something in the Standard related to the sizes (and alignments)
that I missed, and it might actually impose certain limitations thus
giving programmers more leeway when it comes to determining type sizes.

I don't think so.
 
F

Francis Glassborow

Bruce. said:
John Harrison said:
Since you aren't worried about padding bytes the obvious answer is

typedef struct
{
int var1;
int var2;
int var3;
char var4[ 1024 - 3*sizeof(int) ];
} MYSTRUCT;

Thanks but my example was oversimplified to keep it brief. The actual
structures are much more complex, too complex for a solution like that.

I guess what I was looking for doesn't exist.

But thanks anyway.

Bruce.
Try:

struct mystruct {
struct {
int var1;
int var2;
int var3;
} header;
char data[1024 - sizeof(header)];
}

we still have a slight padding issue because in theory the compiler
could add padding between header and data but in general it won't though
there maybe alignment padding at the end of header but that will be part
of the header object and so included in the sizeof(header).


The above method also has the advantage that it is more maintainable
(easier to change type of a field in the header or add new fields to the
header specification.
 
V

Victor Bazarov

Francis said:
Bruce. said:
John Harrison said:
Since you aren't worried about padding bytes the obvious answer is

typedef struct
{
int var1;
int var2;
int var3;
char var4[ 1024 - 3*sizeof(int) ];
} MYSTRUCT;

Thanks but my example was oversimplified to keep it brief. The
actual structures are much more complex, too complex for a solution
like that. I guess what I was looking for doesn't exist.

But thanks anyway.

Bruce.
Try:

struct mystruct {
struct {
int var1;
int var2;
int var3;
} header;
char data[1024 - sizeof(header)];
}

we still have a slight padding issue because in theory the compiler
could add padding between header and data but in general it won't
though there maybe alignment padding at the end of header but that
will be part of the header object and so included in the
sizeof(header).

The above method also has the advantage that it is more maintainable
(easier to change type of a field in the header or add new fields to
the header specification.

I just thought of a slightly different way:

struct mystruct {
int var1, var2, var3;
char data[1024 - offsetof(data)];
};

Should that alleviate any trouble with possible padding?

V
 
V

Victor Bazarov

Victor said:
Francis said:
Bruce. said:
Since you aren't worried about padding bytes the obvious answer is

typedef struct
{
int var1;
int var2;
int var3;
char var4[ 1024 - 3*sizeof(int) ];
} MYSTRUCT;

Thanks but my example was oversimplified to keep it brief. The
actual structures are much more complex, too complex for a solution
like that. I guess what I was looking for doesn't exist.

But thanks anyway.

Bruce.
Try:

struct mystruct {
struct {
int var1;
int var2;
int var3;
} header;
char data[1024 - sizeof(header)];
}

we still have a slight padding issue because in theory the compiler
could add padding between header and data but in general it won't
though there maybe alignment padding at the end of header but that
will be part of the header object and so included in the
sizeof(header).

The above method also has the advantage that it is more maintainable
(easier to change type of a field in the header or add new fields to
the header specification.

I just thought of a slightly different way:

struct mystruct {
int var1, var2, var3;
char data[1024 - offsetof(data)];

Of course this ought to be

char data[1024 - offsetof(mystruct, data)];
};

Should that alleviate any trouble with possible padding?

V
 
B

Bruce.

Victor Bazarov said:
I just thought of a slightly different way:

struct mystruct {
int var1, var2, var3;
char data[1024 - offsetof(mystruct, data)];
};

Unfortunately that won't compile:

error C2027: use of undefined type 'mystruct'

Bruce.
 
J

James Dennett

Victor said:
Victor said:
Francis said:
Bruce. wrote:
Since you aren't worried about padding bytes the obvious answer is

typedef struct
{
int var1;
int var2;
int var3;
char var4[ 1024 - 3*sizeof(int) ];
} MYSTRUCT;
Thanks but my example was oversimplified to keep it brief. The
actual structures are much more complex, too complex for a solution
like that. I guess what I was looking for doesn't exist.

But thanks anyway.

Bruce.


Try:

struct mystruct {
struct {
int var1;
int var2;
int var3;
} header;
char data[1024 - sizeof(header)];
}

we still have a slight padding issue because in theory the compiler
could add padding between header and data but in general it won't
though there maybe alignment padding at the end of header but that
will be part of the header object and so included in the
sizeof(header).

The above method also has the advantage that it is more maintainable
(easier to change type of a field in the header or add new fields to
the header specification.
I just thought of a slightly different way:

struct mystruct {
int var1, var2, var3;
char data[1024 - offsetof(data)];

Of course this ought to be

char data[1024 - offsetof(mystruct, data)];
};

Should that alleviate any trouble with possible padding?

It shouldn't even compile, as offsetof requires mystruct
to be complete, and hence can't be used in the definition
of mystruct.

-- James
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,781
Messages
2,569,615
Members
45,300
Latest member
RoryCarlso

Latest Threads

Top