变长结构体的表示方法

变长结构体的表示方法

分类: 编程 798人阅读 评论(2) 收藏 举报

转载请注明出处: http://blog.csdn.net/zhangyang0402/archive/2010/08/07/5795614.aspx

 

在Linux程序中,经常会看到形如下面的结构体定义
struct xfrm_algo {
 char  alg_name[64];
 unsigned int alg_key_len;    /* in bits */
 char  alg_key[0]; //有的地方这样写char alg_key[]
};

这里,最奇怪的是结构体最后一个元素, 是一个零长度的字符数组

这里先解释一下结构体的作用。
xfrm_algo是一个定义密钥算法的结构体,alg_name存放算法名称,alg_key_len存放密钥长度(单位是bit),all_key存放密钥. 因为同一个算法,有可能会使用不同长度的密钥。

如AES, 就有128位、192位和256位三种密钥。 所以,在定义这样一个密钥算法的结构体时,就要求不定长的结构体,而零长数组就可实现这一点。


当然,我们也可以使用指针来代替

struct xfrm_algo {
 char  alg_name[64];
 unsigned int alg_key_len;    /* in bits */
 char *  alg_key;
};

下面,分别用指针和零长数组实现不定长结构体。

方法1:定义一个xfrm_algo结构体变量,再为alg_key成员动态创建内存

这种情况下,实际的xfrm_algo结构体和密钥是分离的

[cpp] view plain copy print ?
  1. #include<stdio.h>   
  2. #include<stdlib.h>   
  3. #include<string.h>   
  4.   
  5. void print_hex( unsigned char *buf, int len);  
  6.   
  7. struct xfrm_algo  
  8. {  
  9.         char             alg_name[64];  
  10.         unsigned int     alg_key_len;  
  11.         unsigned char *  alg_key;  
  12. };  
  13.   
  14. int main( void )  
  15. {  
  16.         char alg[] = "AES";  
  17.         unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /  
  18.                                 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };  
  19.         struct xfrm_algo algo1;  
  20.         memcpy( algo1.alg_name, alg, sizeof(alg) );  
  21.         algo1.alg_key_len = sizeof(key) * 8;  
  22.         if( ( algo1.alg_key = (unsigned char *)malloc( sizeof(key) ) ) == NULL )  
  23.         {  
  24.                 perror("malloc");  
  25.                 return -1;  
  26.         }  
  27.         memcpy( algo1.alg_key, key, sizeof(key) );  
  28.         printf("sizeof(struct xfrm_algo) = %d/n"sizeof(struct xfrm_algo));  
  29.         printf("algo1: 0x%08x/n", &algo1);  
  30.         printf("/talg_name   : 0x%08x(%s)/n", algo1.alg_name, algo1.alg_name);  
  31.         printf("/talg_key_len: 0x%08x(%d)/n", &algo1.alg_key_len, algo1.alg_key_len);  
  32.         printf("/talg_key    : 0x%08x", algo1.alg_key);  
  33.         print_hex( algo1.alg_key, sizeof(key) );  
  34.         free(algo1.alg_key);  
  35.         return 0;  
  36. }  
  37.   
  38. void print_hex( unsigned char *buf, int len)  
  39. {  
  40.         int i = 0;  
  41.         printf("(");  
  42.         for( i = 0; i < len; i++ )  
  43.         {  
  44.                 printf("0x%02x ", buf[i]);  
  45.         }  
  46.         printf(")/n");  
  47. }  
#include<stdio.h> #include<stdlib.h> #include<string.h> void print_hex( unsigned char *buf, int len); struct xfrm_algo { char alg_name[64]; unsigned int alg_key_len; unsigned char * alg_key; }; int main( void ) { char alg[] = "AES"; unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, / 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; struct xfrm_algo algo1; memcpy( algo1.alg_name, alg, sizeof(alg) ); algo1.alg_key_len = sizeof(key) * 8; if( ( algo1.alg_key = (unsigned char *)malloc( sizeof(key) ) ) == NULL ) { perror("malloc"); return -1; } memcpy( algo1.alg_key, key, sizeof(key) ); printf("sizeof(struct xfrm_algo) = %d/n", sizeof(struct xfrm_algo)); printf("algo1: 0x%08x/n", &algo1); printf("/talg_name : 0x%08x(%s)/n", algo1.alg_name, algo1.alg_name); printf("/talg_key_len: 0x%08x(%d)/n", &algo1.alg_key_len, algo1.alg_key_len); printf("/talg_key : 0x%08x", algo1.alg_key); print_hex( algo1.alg_key, sizeof(key) ); free(algo1.alg_key); return 0; } void print_hex( unsigned char *buf, int len) { int i = 0; printf("("); for( i = 0; i < len; i++ ) { printf("0x%02x ", buf[i]); } printf(")/n"); }

 

执行结果:
$ ./struct_pointer1
sizeof(struct xfrm_algo) = 72
algo1: 0xbff54108
        alg_name   : 0xbff54108(AES)
        alg_key_len: 0xbff54148(128)
        alg_key    : 0x09b2f008(0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f )

从输出可观察到, alg_key_len与alg_key是分离的

 

方法2: 直接为xfrm_algo和已知的密钥动态创建内存

此时,xfrm_algo结构体和密钥是连续的。

[cpp] view plain copy print ?
  1. #include<stdio.h>   
  2. #include<stdlib.h>   
  3. #include<string.h>   
  4.   
  5. void print_hex( unsigned char *buf, int len);  
  6.   
  7. struct xfrm_algo  
  8. {  
  9.         char             alg_name[64];  
  10.         unsigned int     alg_key_len;  
  11.         unsigned char *  alg_key;  
  12. };  
  13.   
  14. int main( void )  
  15. {  
  16.         char alg[] = "AES";  
  17.         unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /  
  18.                                 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };  
  19.         struct xfrm_algo *palgo = NULL;  
  20.         if( ( palgo = (struct xfrm_algo * )malloc( sizeof(struct xfrm_algo) + sizeof(key) ) ) ==  NULL )  
  21.         {  
  22.                 perror("malloc");  
  23.                 return -1;  
  24.         }  
  25.         memcpy( palgo->alg_name, alg, sizeof(alg) );  
  26.         palgo->alg_key_len = sizeof(key) * 8;  
  27.         palgo->alg_key = (unsigned char *)( palgo + 1 );  
  28.         memcpy( palgo->alg_key, key, sizeof(key) );  
  29.         printf("sizeof(struct xfrm_algo) = %d/n"sizeof(struct xfrm_algo));  
  30.         printf("palgo: 0x%08x/n", palgo);  
  31.         printf("/talg_name   : 0x%08x(%s)/n", palgo->alg_name, palgo->alg_name);  
  32.         printf("/talg_key_len: 0x%08x(%d)/n", &palgo->alg_key_len, palgo->alg_key_len);  
  33.         printf("/talg_key    : 0x%08x", palgo->alg_key);  
  34.         print_hex( palgo->alg_key, sizeof(key) );  
  35.         free(palgo);  
  36.         return 0;  
  37. }  
  38.   
  39. void print_hex( unsigned char *buf, int len)  
  40. {  
  41.         int i = 0;  
  42.         printf("(");  
  43.         for( i = 0; i < len; i++ )  
  44.         {  
  45.                 printf("0x%02x ", buf[i]);  
  46.         }  
  47.         printf(")/n");  
  48. }  
#include<stdio.h> #include<stdlib.h> #include<string.h> void print_hex( unsigned char *buf, int len); struct xfrm_algo { char alg_name[64]; unsigned int alg_key_len; unsigned char * alg_key; }; int main( void ) { char alg[] = "AES"; unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, / 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; struct xfrm_algo *palgo = NULL; if( ( palgo = (struct xfrm_algo * )malloc( sizeof(struct xfrm_algo) + sizeof(key) ) ) == NULL ) { perror("malloc"); return -1; } memcpy( palgo->alg_name, alg, sizeof(alg) ); palgo->alg_key_len = sizeof(key) * 8; palgo->alg_key = (unsigned char *)( palgo + 1 ); memcpy( palgo->alg_key, key, sizeof(key) ); printf("sizeof(struct xfrm_algo) = %d/n", sizeof(struct xfrm_algo)); printf("palgo: 0x%08x/n", palgo); printf("/talg_name : 0x%08x(%s)/n", palgo->alg_name, palgo->alg_name); printf("/talg_key_len: 0x%08x(%d)/n", &palgo->alg_key_len, palgo->alg_key_len); printf("/talg_key : 0x%08x", palgo->alg_key); print_hex( palgo->alg_key, sizeof(key) ); free(palgo); return 0; } void print_hex( unsigned char *buf, int len) { int i = 0; printf("("); for( i = 0; i < len; i++ ) { printf("0x%02x ", buf[i]); } printf(")/n"); }

 

执行结果:
$ ./struct_pointer2
sizeof(struct xfrm_algo) = 72
palgo: 0x096bd008
        alg_name   : 0x096bd008(AES)
        alg_key_len: 0x096bd048(128)
        alg_key    : 0x096bd050(0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f )

从输出可观察到, alg_key_len与alg_key是连续的。这里,alg_key似乎是多余的,因为我们总能使用(unsigned char *)( palgo + 1 )得到key的首地址。
 
方法3:零长度数组

在标准C语言中,是不允许零长度数组的。但 GNU C 允许。

 

[cpp] view plain copy print ?
  1. #include<stdio.h>   
  2. #include<stdlib.h>   
  3. #include<string.h>   
  4.   
  5. void print_hex( unsigned char *buf, int len);  
  6.   
  7. struct xfrm_algo  
  8. {  
  9.         char             alg_name[64];  
  10.         unsigned int     alg_key_len;  
  11.         unsigned char    alg_key[0];  
  12. };  
  13.   
  14. int main( void )  
  15. {  
  16.         char alg[] = "AES";  
  17.         unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /  
  18.                                 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };  
  19.         struct xfrm_algo *palgo = NULL;  
  20.         if( ( palgo = (struct xfrm_algo *)malloc( sizeof(struct xfrm_algo) + sizeof(key) ) ) ==  NULL )  
  21.         {  
  22.                 perror("malloc");  
  23.                 return -1;  
  24.         }  
  25.         memcpy( palgo->alg_name, alg, sizeof(alg) );  
  26.         palgo->alg_key_len = sizeof(key) * 8;  
  27.         memcpy( palgo->alg_key, key, sizeof(key) );  
  28.         printf("sizeof(struct xfrm_algo) = %d/n"sizeof(struct xfrm_algo));  
  29.         printf("palgo: 0x%08x/n", palgo);  
  30.         printf("/talg_name   : 0x%08x(%s)/n", palgo->alg_name, palgo->alg_name);  
  31.         printf("/talg_key_len: 0x%08x(%d)/n", &(palgo->alg_key_len), palgo->alg_key_len);  
  32.         printf("/talg_key    : 0x%08x", palgo->alg_key);  
  33.         print_hex( palgo->alg_key, palgo->alg_key_len / 8 );  
  34.         free(palgo);  
  35.         return 0;  
  36. }  
  37.   
  38. void print_hex( unsigned char *buf, int len)  
  39. {  
  40.         int i = 0;  
  41.         printf("(");  
  42.         for( i = 0; i < len; i++ )  
  43.         {  
  44.                 printf("0x%02x ", buf[i]);  
  45.         }  
  46.         printf(")/n");  
  47. }  
#include<stdio.h> #include<stdlib.h> #include<string.h> void print_hex( unsigned char *buf, int len); struct xfrm_algo { char alg_name[64]; unsigned int alg_key_len; unsigned char alg_key[0]; }; int main( void ) { char alg[] = "AES"; unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, / 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; struct xfrm_algo *palgo = NULL; if( ( palgo = (struct xfrm_algo *)malloc( sizeof(struct xfrm_algo) + sizeof(key) ) ) == NULL ) { perror("malloc"); return -1; } memcpy( palgo->alg_name, alg, sizeof(alg) ); palgo->alg_key_len = sizeof(key) * 8; memcpy( palgo->alg_key, key, sizeof(key) ); printf("sizeof(struct xfrm_algo) = %d/n", sizeof(struct xfrm_algo)); printf("palgo: 0x%08x/n", palgo); printf("/talg_name : 0x%08x(%s)/n", palgo->alg_name, palgo->alg_name); printf("/talg_key_len: 0x%08x(%d)/n", &(palgo->alg_key_len), palgo->alg_key_len); printf("/talg_key : 0x%08x", palgo->alg_key); print_hex( palgo->alg_key, palgo->alg_key_len / 8 ); free(palgo); return 0; } void print_hex( unsigned char *buf, int len) { int i = 0; printf("("); for( i = 0; i < len; i++ ) { printf("0x%02x ", buf[i]); } printf(")/n"); }

 


执行结果:

$ ./struct_array
sizeof(struct xfrm_algo) = 68
palgo: 0x0980d008
        alg_name   : 0x0980d008(AES)
        alg_key_len: 0x0980d048(128)
        alg_key    : 0x0980d04c(0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f )

xfrm_algo结构体大小为68个字节, alg_key[0]不占存储空间,和方法1、2相比,少了个unsigned char *指针,但可移植性不比前两种方法。 

你可能感兴趣的:(编程)