简体   繁体   中英

Setting the size of an array inside a struct with a value of another value within the same struct, in C

    struct {
        uint16 msg_length;
        uint8 msg_type;
        ProtocolVersion version;
        uint16 cipher_spec_length;
        uint16 session_id_length;
        uint16 challenge_length;
        V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];
        opaque session_id[V2ClientHello.session_id_length];
        opaque challenge[V2ClientHello.challenge_length;
    } V2ClientHello;

Is it possible to do something similar to the above ( http://tools.ietf.org/html/rfc5246 )? If so how do I go about coding this inside C?

To be more specific this line in the struct:

V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];


Uses:

V2ClientHello.cipher_spec_length


Which is defined in the same struct, to set the length of the array.

C does not support dynamic-sized arrays. To achieve your goal, you can use a pointer of type V2CipherSpec as structure variable and allocate memory at a later stage using the V2ClientHello.cipher_spec_length value.

Absolutely not. C does not have dynamic-size arrays. Instead, we can rely on tricks like this:

struct {
    uint16 msg_length;
    uint8 msg_type;
    ProtocolVersion version;
    uint16 cipher_spec_length;
    uint16 session_id_length;
    uint16 challenge_length;
    char extra[0]; // or 1 if your compiler hates this
} V2ClientHello;

Then, do not create instances of this struct directly, but rather via malloc():

struct V2ClientHello* hello = malloc(sizeof(V2ClientHello) + 
    len1*sizeof(V2CipherSpec) + len2 + len3);

Now you have a dynamically-allocated structure of the size you need. You can make accessor functions to get the "extra" fields:

V2CipherSpec* get_spec(V2ClientHello* hello, int idx) {
    assert(idx < hello->cipher_spec_length);
    return ((V2CipherSpec*)&hello->extra)[idx];
}

And of course you can wrap up the malloc() call inside a create routine which takes the sizes of all three dynamic parts and does everything in one place for robustness.

The shown code from the RFC is pseudo code, you can not implement it as shown.

You need to allocate these arrays manually depending on V2ClientHello.cipher_spec_length and the other length specification fields, once their values are known.

Value of "V2ClientHello.cipher_spec_length" is not available at compile time. You can not specify the size of an array at run time, instead use:

V2CipherSpec *cipher_specs;

in struct and use malloc or calloc to allocate a block of memory at run time.

V2ClientHello.cipher_specs = (V2CipherSpec *)malloc(V2ClientHello.cipher_spec_length);

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