I am working on a project where I need to specify the information I get through UDP in a struct. The UDP sends structs in the form of packets which I need to unpack. Some of these packets contain an array of another struct. However, I get the error:
CS0650 Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type.
How do I do this correctly? I tried using the unsafe method, but that is only allowed for "standard" datatypes like: float, int, etc.
This is my struct where I want to put the data:
[StructLayout(LayoutKind.Explicit, Pack = 0, Size = 632)]
public struct PacketSessionData
{
[FieldOffset(0)]
public PacketHeader m_header; // Header
[FieldOffset(24)]
public byte m_weather; // Weather - 0 = clear, 1 = light cloud, 2 = overcast
// 3 = light rain, 4 = heavy rain, 5 = storm
[FieldOffset(25)]
public sbyte m_trackTemperature; // Track temp. in degrees celsius
[FieldOffset(26)]
public sbyte m_airTemperature; // Air temp. in degrees celsius
[FieldOffset(27)]
public byte m_totalLaps; // Total number of laps in this race
[FieldOffset(28)]
public UInt16 m_trackLength; // Track length in metres
[FieldOffset(30)]
public byte m_sessionType; // 0 = unknown, 1 = P1, 2 = P2, 3 = P3, 4 = Short P
// 5 = Q1, 6 = Q2, 7 = Q3, 8 = Short Q, 9 = OSQ
// 10 = R, 11 = R2, 12 = R3, 13 = Time Trial
[FieldOffset(31)]
public sbyte m_trackId; // -1 for unknown, see appendix
[FieldOffset(32)]
public byte m_formula; // Formula, 0 = F1 Modern, 1 = F1 Classic, 2 = F2,
// 3 = F1 Generic, 4 = Beta, 5 = Supercars
// 6 = Esports, 7 = F2 2021
[FieldOffset(33)]
public UInt16 m_sessionTimeLeft; // Time left in session in seconds
[FieldOffset(35)]
public UInt16 m_sessionDuration; // Session duration in seconds
[FieldOffset(37)]
public byte m_pitSpeedLimit; // Pit speed limit in kilometres per hour
[FieldOffset(38)]
public byte m_gamePaused; // Whether the game is paused – network game only
[FieldOffset(39)]
public byte m_isSpectating; // Whether the player is spectating
[FieldOffset(40)]
public byte m_spectatorCarIndex; // Index of the car being spectated
[FieldOffset(41)]
public byte m_sliProNativeSupport; // SLI Pro support, 0 = inactive, 1 = active
[FieldOffset(42)]
public byte m_numMarshalZones; // Number of marshal zones to follow
[FieldOffset(43)]
public MarshalZone m_marshalZones[21]; // List of marshal zones – max 21
[FieldOffset(148)]
public byte m_safetyCarStatus; // 0 = no safety car, 1 = full
// 2 = virtual, 3 = formation lap
[FieldOffset(149)]
public byte m_networkGame; // 0 = offline, 1 = online
[FieldOffset(150)]
public byte m_numWeatherForecastSamples; // Number of weather samples to follow
[FieldOffset(151)]
public WeatherForecastSample m_weatherForecastSamples[56]; // Array of weather forecast samples
[FieldOffset(599)]
public byte m_forecastAccuracy; // 0 = Perfect, 1 = Approximate
[FieldOffset(600)]
public byte m_aiDifficulty; // AI Difficulty rating – 0-110
[FieldOffset(601)]
public UInt32 m_seasonLinkIdentifier; // Identifier for season - persists across saves
[FieldOffset(605)]
public UInt32 m_weekendLinkIdentifier; // Identifier for weekend - persists across saves
[FieldOffset(609)]
public UInt32 m_sessionLinkIdentifier; // Identifier for session - persists across saves
[FieldOffset(613)]
public byte m_pitStopWindowIdealLap; // Ideal lap to pit on for current strategy (player)
[FieldOffset(614)]
public byte m_pitStopWindowLatestLap; // Latest lap to pit on for current strategy (player)
[FieldOffset(615)]
public byte m_pitStopRejoinPosition; // Predicted position to rejoin at (player)
[FieldOffset(616)]
public byte m_steeringAssist; // 0 = off, 1 = on
[FieldOffset(617)]
public byte m_brakingAssist; // 0 = off, 1 = low, 2 = medium, 3 = high
[FieldOffset(618)]
public byte m_gearboxAssist; // 1 = manual, 2 = manual & suggested gear, 3 = auto
[FieldOffset(619)]
public byte m_pitAssist; // 0 = off, 1 = on
[FieldOffset(620)]
public byte m_pitReleaseAssist; // 0 = off, 1 = on
[FieldOffset(621)]
public byte m_ERSAssist; // 0 = off, 1 = on
[FieldOffset(622)]
public byte m_DRSAssist; // 0 = off, 1 = on
[FieldOffset(623)]
public byte m_dynamicRacingLine; // 0 = off, 1 = corners only, 2 = full
[FieldOffset(624)]
public byte m_dynamicRacingLineType; // 0 = 2D, 1 = 3D
[FieldOffset(625)]
public byte m_gameMode; // Game mode id - see appendix
[FieldOffset(626)]
public byte m_ruleSet; // Ruleset - see appendix
[FieldOffset(627)]
public UInt32 m_timeOfDay; // Local time of day - minutes since midnight
[FieldOffset(631)]
public byte m_sessionLength; // 0 = None, 2 = Very Short, 3 = Short, 4 = Medium, 5 = Medium Long, 6 = Long, 7 = Full
};
And these are the structs from which I need to create an array in the previous struct:
[StructLayout(LayoutKind.Explicit, Pack = 0, Size = 5)]
public struct MarshalZone
{
[FieldOffset(0)]
public float m_zoneStart; // Fraction (0..1) of way through the lap the marshal zone starts
[FieldOffset(4)]
public sbyte m_zoneFlag; // -1 = invalid/unknown, 0 = none, 1 = green, 2 = blue, 3 = yellow, 4 = red
};
[StructLayout(LayoutKind.Explicit, Pack = 0, Size = 8)]
public struct WeatherForecastSample
{
[FieldOffset(0)]
public byte m_sessionType; // 0 = unknown, 1 = P1, 2 = P2, 3 = P3, 4 = Short P, 5 = Q1
// 6 = Q2, 7 = Q3, 8 = Short Q, 9 = OSQ, 10 = R, 11 = R2
// 12 = R3, 13 = Time Trial
[FieldOffset(1)]
public byte m_timeOffset; // Time in minutes the forecast is for
[FieldOffset(2)]
public byte m_weather; // Weather - 0 = clear, 1 = light cloud, 2 = overcast
// 3 = light rain, 4 = heavy rain, 5 = storm
[FieldOffset(3)]
public sbyte m_trackTemperature; // Track temp. in degrees Celsius
[FieldOffset(4)]
public sbyte m_trackTemperatureChange; // Track temp. change – 0 = up, 1 = down, 2 = no change
[FieldOffset(5)]
public sbyte m_airTemperature; // Air temp. in degrees celsius
[FieldOffset(6)]
public sbyte m_airTemperatureChange; // Air temp. change – 0 = up, 1 = down, 2 = no change
[FieldOffset(7)]
public byte m_rainPercentage; // Rain percentage (0-100)
};
Edit:
After testing the solutions in the comments I get the following exception thrown:

This is the code:
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 21)]
[FieldOffset(43)]
public MarshalZone[] m_marshalZones; // List of marshal zones – max 21
[FieldOffset(148)]
public byte m_safetyCarStatus; // 0 = no safety car, 1 = full
// 2 = virtual, 3 = formation lap
[FieldOffset(149)]
public byte m_networkGame; // 0 = offline, 1 = online
[FieldOffset(150)]
public byte m_numWeatherForecastSamples; // Number of weather samples to follow
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 56)]
[FieldOffset(151)]
public WeatherForecastSample[] m_weatherForecastSamples; // Array of weather forecast samples
public MarshalZone[] m_marshalZones;(so no size). But how that works with[FieldOffset]I don't know