简体   繁体   中英

Structures containing conditional fields in C

I'm attempting to implement a protocol standard and I'm having a bit of trouble with their concept of conditional fields. They are defined as fields that are present or absent depending on some condition. The example they give is as follows:

    uint16 Pressure;
    enum VehicleType { car = 0, motorbike = 1};
    struct TirePressureInfo {
                    VehicleType type;
                    select (type)
                    {
                    case car:
                            Pressure frontLeft;
                            Pressure frontRight;
                            Pressure rearLeft;
                            Pressure rearRight;
                    case motorbike:
                            Pressure front;
                            Pressure rear;
                    }
            }

I'm unaware of anyway to make this work in C, or if it's even possible. I can't think of anyway to implement this. One thing to note, is this is going to be implemented in a Linux Kernel Module, so I'm a bit restricted there as well.

            struct {
                    uint8 protocol_version;
                    ContentType type;
                    select (type) {
                    case unsecured :
                    opaque data<var>;
                    case signed, signed_partial_payload,
                    signed_external_payload:
                    SignedData signed_data;
                    case signed_wsa:
                    SignedWsa signed_wsa;
                    case encrypted :
                    EncryptedData encrypted_data;
                    case crl_request :
                    CrlRequest crl_request;
                    case crl :
                    Crl crl;
                    case other_value:
                    opaque data<var>;
                    }
            } 1609Dot2Data;




    struct {
            SignerIdentifierType type;
            select (type) {
            case self: ;
            case certificate_digest_with_ecdsap224 :
            case certificate_digest_with_ecdsap256 :
                    HashedId8 digest;
                    opaque data<var>;
            case certificate:
                    Certificate certificate;
            case certificate_chain:
                    Certificate certificates<var>;
            case certificate_digest_with_other_algorithm :
                    Signer signer;
                    PKAlgorithm algorithm;
                    HashedId8 digest;
            case other_value:
                    opaque id<var>;
            }
    } SignerIdentifier;

You can use a union :

uint16 Pressure;
enum VehicleType { CAR = 0, MOTORBIKE = 1};
struct TirePressureInfo {
  VehicleType type;
  union {
    struct {
      Pressure frontLeft;
      Pressure frontRight;
      Pressure rearLeft;
      Pressure rearRight;
    } car;
    struct {
      Pressure front;
      Pressure rear;
    } motorbike;
  } data;
};

So then you can set it like:

struct TirePressureInfo info;
info.type = CAR;
info.data.car.frontLeft  = 35;
info.data.car.frontRight = 35;
info.data.car.rearLeft   = 32;
info.data.car.rearRight  = 32;

or if you want to define a MOTORBIKE :

struct TirePressureInfo info;
info.type = MOTORBIKE;
info.data.motorbike.front = 38;
info.data.motorbike.rear  = 40;

When you read from it, you should check the type :

switch ( info.type ) {
case CAR:
    /* read info.data.car fields */
    break;
case MOTORBIKE:
    /* read info.data.motorbike fields */
    break;
default:
    /* Some data integrity problem */
}

If you are certain that you only ever need a struct car or struct motorbike at a time (depending on the value of type ), then there is no need to waste space by having every TirePressureInfo include both struct car 's fields and struct motorbike 's fields. Using a union makes the struct car and struct motorbike occupy the same place in memory. The actual size of the union is the greater of the two . This just gives you different ways to read and write to the same place in memory.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM