What Can I Expect From This Union?

M

Mike

Within the following structure, TopStruct, I'd like to create 3 other
structures, 2 of which make up a union. The first structure will always
contain some data that I need and should never be overwritten, i.e. should
not be part of the union. The remaining 2, UnionData1 and UnionData2, make
up the union and are populated as needed.

I want to be certain that this code will work as planned. Specifically, if
the field offsets of the first union members are set to '0', will they
overwrite the data in the first structure, AlwaysContainsData? Or should
they be changed to the values indicated in the inline comments?

Essentially, I don't know if the FieldOffset attribute applies to the struct
in which it's called, e.g. UnionData1, or to the top-level struct,
TopStruct:


public struct TopStruct
{
[StructLayout( LayoutKind.Sequential )]
public struct AlwaysContainsData // Contains 262 bytes of data.
{
public short dataType;
public short rmsVolt;
public short rmsCurr;

[MarshalAs( UnmanagedType.ByValArray, SizeConst = 128 )]
public short[] waveform;
}

// Begin the structs for the union.
[ StructLayout( LayoutKind.Explicit ) ]
public struct UnionData1
{
[ MarshalAs( UnmanagedType.ByValArray, SizeConst = 128 ) ]
[ FieldOffset( 0 ) ] // or should it be "FieldOffset( 262 )"
?
public short[] waveform2;
}

[ StructLayout( LayoutKind.Explicit ) ]
public struct UnionData2
{
[ MarshalAs( UnmanagedType.ByValArray, SizeConst = 128) ]
[ FieldOffset( 0 ) ] // or should it be "FieldOffset( 262 )"
?
public short[] waveform2;

[ MarshalAs( UnmanagedType.ByValArray, SizeConst = 128) ]
[ FieldOffset( 128 ) ] // or should it be "FieldOffset( 390 )"
?
public short[] waveform3;

}

} // End of TopStruct
 
J

Jeffrey Tan[MSFT]

Hi Mike,

Because the FieldOffsetAttribute is applied to the UnionData class, I think
your FieldOffset
should be number relative to the UnionData class.
The member of the UnionData class will alloc memory after the first
structure AlwaysContainsData.

I think you can determine this by creating a unmanaged dlll consuming the
union.

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| From: "Mike" <[email protected]>
| Subject: What Can I Expect From This Union?
| Date: Tue, 2 Sep 2003 15:15:17 -0400
| Lines: 57
| X-Priority: 3
| X-MSMail-Priority: Normal
| X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
| Message-ID: <[email protected]>
| Newsgroups: microsoft.public.dotnet.languages.csharp
| NNTP-Posting-Host: dialup-171.75.39.7.dial1.washington1.level3.net
171.75.39.7
| Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP11.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:181638
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| Within the following structure, TopStruct, I'd like to create 3 other
| structures, 2 of which make up a union. The first structure will always
| contain some data that I need and should never be overwritten, i.e. should
| not be part of the union. The remaining 2, UnionData1 and UnionData2,
make
| up the union and are populated as needed.
|
| I want to be certain that this code will work as planned. Specifically,
if
| the field offsets of the first union members are set to '0', will they
| overwrite the data in the first structure, AlwaysContainsData? Or should
| they be changed to the values indicated in the inline comments?
|
| Essentially, I don't know if the FieldOffset attribute applies to the
struct
| in which it's called, e.g. UnionData1, or to the top-level struct,
| TopStruct:
|
|
| public struct TopStruct
| {
| [StructLayout( LayoutKind.Sequential )]
| public struct AlwaysContainsData // Contains 262 bytes of data.
| {
| public short dataType;
| public short rmsVolt;
| public short rmsCurr;
|
| [MarshalAs( UnmanagedType.ByValArray, SizeConst = 128 )]
| public short[] waveform;
| }
|
| // Begin the structs for the union.
| [ StructLayout( LayoutKind.Explicit ) ]
| public struct UnionData1
| {
| [ MarshalAs( UnmanagedType.ByValArray, SizeConst = 128 ) ]
| [ FieldOffset( 0 ) ] // or should it be "FieldOffset( 262
)"
| ?
| public short[] waveform2;
| }
|
| [ StructLayout( LayoutKind.Explicit ) ]
| public struct UnionData2
| {
| [ MarshalAs( UnmanagedType.ByValArray, SizeConst = 128) ]
| [ FieldOffset( 0 ) ] // or should it be "FieldOffset( 262
)"
| ?
| public short[] waveform2;
|
| [ MarshalAs( UnmanagedType.ByValArray, SizeConst = 128) ]
| [ FieldOffset( 128 ) ] // or should it be "FieldOffset( 390
)"
| ?
| public short[] waveform3;
|
| }
|
| } // End of TopStruct
|
|
|
 
M

Mattias Sjögren

Mike,
Essentially, I don't know if the FieldOffset attribute applies to the struct
in which it's called, e.g. UnionData1, or to the top-level struct,
TopStruct:

The offset is relative to the beginning of the "union" struct itself,
not any containing type.

Note that declaring a type nested inside another type does not
automatically give you a member of that nested type in the containing
type. Specifically, the TopStruct as it's written right now doesn't
have any members.



Mattias
 
M

Mike

Thanks for your reply, Mattias.

If the offset is relative to the beginning of the union struct rather than
the containing struct, then the idea of UnionData1 and UnionData2 occupying
the same memory location is incorrect, isn't it?

To clarify matters, I wanted to have a data structure, TopStruct, that
contained some data that will be always populated (AlwaysContainsData
struct) by the data stream, and other data that would populate one of the
union structs or the other (UnionData1 or UnionData2), but not both. Hence,
I don't need to allocate memory for more than one union struct at a time,
though I need all the members within it.

Can I accomplish this?


-Mike
 
M

Mattias Sjögren

If the offset is relative to the beginning of the union struct rather than
the containing struct, then the idea of UnionData1 and UnionData2 occupying
the same memory location is incorrect, isn't it?

No, the idea is correct. But it's not always possible to realize. The
fact that you can't overlay object types with value types restricts
what you can do with explicit layout types.

Hence,
I don't need to allocate memory for more than one union struct at a time,

The effective size of a struct with explicit layout (union) is the
same regardless of which part of the union you use, so this will not
necessarily reduce memory allocation.



Mattias
 
M

Mike

100,

You've given me food for thought. Thanks for your help.


-Mike

100 said:
Hi Mike
Is it posible to do something like the following. I haven't tried, though.

[ StructLayout( LayoutKind.Explicit ) ]
public struct TopStruct
{
[StructLayout( LayoutKind.Sequential )]
public struct AlwaysContainsData // Contains 262 bytes of data.
{
....
}
[ StructLayout( LayoutKind.Explicit ) ]
public struct UnionData1
{
.....
}

[ StructLayout( LayoutKind.Explicit ) ]
public struct UnionData2
{
.....
}

[ FieldOffset( 0 ) ]
public AlwaysContainsData alwaysContainsData ;
[ FieldOffset( 262) ]
public UnionData1 unionData1
[ FieldOffset( 262) ]
public UnionData2 UnionData2
}

So if it works. changing
a field from unionData1 should change unionData2.

TopStruct topStruct = new TopStruct();
topStruct.unionData1.SomeField = ......

In your original example you made a mistake. Decalring a struct nested in
another struct/class doesn't make its members part of the outer struct/class
members. It just changes the structure name scope.
So the data fields of AlwaysContainsData, UnionData1 and UnionData2 are not
part of the TopStruct members and setting their members' FieldOffset
attributes cannot be releated to the TopStruct.
This is unlike the C++ anonimous structs and unions. To make them part of
the TopStruct you have to declare member variables of those struct types.

You might be able to do the following as well:

[ StructLayout( LayoutKind.Explicit ) ]
public struct TopStruct
{
[FieldOffset( 0 )]
int FirstAlwaysData;
[FieldOffset( 4 )]
int SecAlwaysData;
[FieldOffset( 8 )] //this and the next field occupy the same
memory
int FirstUnion1Data;
[FieldOffset( 8 )]
int FirstUnion2Data;
}

I haven't tested these ideas, though.

HTH
B\rgds
100
 

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

Top