在结构中使用另一个值的值设置一个数组的大小,在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; 

是否可以做类似上面的事情( http://tools.ietf.org/html/rfc5246 )? 如果是这样,我如何在C内编码呢?

更具体地说,结构中的这一行:

V2CipherSpec cipher_specs [V2ClientHello.cipher_spec_length];

用途:

V2ClientHello.cipher_spec_length

这是在同一个结构中定义的,用于设置数组的长度。

C不支持动态大小的数组。 为了实现目标,可以使用V2CipherSpec类型的指针作为结构变量,并使用V2ClientHello.cipher_spec_length值在稍后阶段分配内存。

绝对不。 C没有动态大小的数组。 相反,我们可以依赖这样的技巧:

 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; 

然后,不要直接创建此结构的实例,而是通过malloc():

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

现在,您拥有了所需大小的动态分配结构。 您可以使用访问器函数来获取“额外”字段:

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

当然,您可以在一个创建例程中包含malloc()调用,该例程获取所有三个动态部分的大小,并在一个位置执行所有操作以获得稳健性。

RFC中显示的代码是伪代码,您无法如图所示实现它。

一旦知道了它们的值,您需要根据V2ClientHello.cipher_spec_length和其他长度规范字段手动分配这些数组。

“V2ClientHello.cipher_spec_length”的值在编译时不可用。 您不能在运行时指定数组的大小,而是使用:

V2CipherSpec * cipher_specs;

在struct中使用malloc或calloc在运行时分配一块内存。

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