C#における構造体(struct)の基礎と応用

構造体のメモリ配置仕様:

構造体インスタンス生成後、メモリ領域が確保されます。

メモリはバイト単位で管理され、
最初に宣言されたフィールドが低位バイト領域に配置されます(リトルエンディアン方式)。

struct MemoryExample
{
    byte field0;     // 0x0000
    int  field4;     // 0x0004
    byte field8;     // 0x0008
    long field16;    // 0x0010
}

C#構造体の特徴:

値型として動作するため、パラメータ渡しや戻り値として頻出します。 クラスと比較してメモリコピー効率が高いため、小型データ構造に適しています。

public unsafe struct DeviceData
{
    public uint FrameID;    // 通信フレームID
    public uint Timestamp;  // デバイス時刻(0.1ms単位)
    public byte TimeValid;  // 時刻有効フラグ
    public byte SendMode;   // 送信モード(0:通常送信, 1:シングル送信)
    public byte RemoteFlag; // リモートフレームフラグ
    public byte Extended;   // 拡張ID使用フラグ
    public byte DataLength; // データ長(最大8バイト)
    public fixed byte Payload[8]; // 通信ペイロード
    public fixed byte Reserved[3]; // 予約領域
}

C言語との構造体比較:

typedef struct _DeviceInfo 
{ 
    unsigned int DeviceID; 
    unsigned int BootCount; 
    unsigned char Status; 
    unsigned char Mode; 
    unsigned char ErrorFlag; 
    unsigned char Extended; 
    unsigned char DataSize; 
    unsigned char Bytes[8]; 
    unsigned char Spare[3]; 
}DeviceInfo, *PDeviceInfo;

// *ポインタ演算子:オブジェクト参照
// &アドレス演算子:オブジェクトアドレス取得

構造体初期化方法(3方式):

// 指定式初期化
struct SampleData
{
    public int Value1;
    public int Value2;
}

SampleData data1 = new SampleData { Value1 = 100, Value2 = 200 };

// 順序式初期化
SampleData data2 = new SampleData(300, 400);

// コンストラクタ式初期化
struct SampleData
{
    public int Value1;
    public int Value2;
    
    public SampleData(int v1, int v2)
    {
        Value1 = v1;
        Value2 = v2;
    }
}

SampleData data3 = new SampleData(500, 600);

明示的レイアウト指定:

[StructLayout(LayoutKind.Explicit, Size=24, CharSet=CharSet.Unicode)]
public struct SystemClock
{
    [FieldOffset(0)] public ushort Year;
    [FieldOffset(2)] public ushort Month;
    [FieldOffset(4)] public ushort DayOfWeek;
    [FieldOffset(6)] public ushort Day;
    [FieldOffset(8)] public ushort Hour;
    [FieldOffset(10)] public ushort Minute;
    [FieldOffset(12)] public ushort Second;
    [FieldOffset(14)] public ushort Millisecond;
    [FieldOffset(16)] public uint TickCount;
}

タグ: C# .NET MemoryLayout ValueTypes StructInitialization

7月4日 21:36 投稿