长度为0的数组

数组的长度在编译时就确定了。长度为0的数组在标准C和C++中是不允许的,编译时会产生错误。但在GNU C中,这种用法却是合法的。最典型的用法就是位于结构体的最后一项,如下图所示:

struct test {
  int a;
  int b[0];
} __attribute((packed)); //改变编译器的对齐方式,让编译器更紧凑地使用内存

注:__attribute__是编译器的特性

typedef struct __attribute__((packed)) {
  UInt8 cmd;     //8位无符号整数
  UInt16 index; //16位无符号整数
} D2MCommand;

typedef struct {
  UInt8 cmd;
  UInt16 index;
} D2MCommandNoAttribute;

NSLog(@"D2MCommand长度: %@", @(sizeof(D2MCommand)));
NSLog(@"D2MCommandNoAttribute长度: %@", @(sizeof(D2MCommandNoAttribute)));

// 打印结果
D2MCommand长度: 3
D2MCommandNoAttribute长度: 4

这样做主要是为了方便内存缓冲区的管理。如果将上面长度为0的数组换为指针,那么在分配内存时,需采用两步:首先 ,为结构体分配一块内存空间;其次再为结构体中的成员变量分配内存空间。这样两次分配的内存时不连续的,需要分别对其进行管理。

struct test1 {
  int a;
  int *b;
} __attribute((packed));

printf("the length of struct test1:%d\n", sizeof(struct test1)); //结果为8

struct test1 *var1;
var1 = (struct test1 *)malloc(sizeof(struct test1));
var1 -> a = 1;
var1 -> b = (int *)malloc(sizeof(int));
*var1 -> b = 1;

free(var1 -> b);
free(var1);

当使用长度为0的数组时,则只需要分配一次内存空间即可。

#define LENGTH 10

struct test2 {
  int a;
  int b[0];
} __attribute((packed));

printf("the length of struct test2:%d\n", sizeof(struct test2)); //结果为4

struct test2 *var2;
var2 = (struct test2*)malloc(sizeof(struct test2) + sizeof(int)*LENGTH);
var2 -> a = 2;
for(int i = 0; i < LENGTH; i++) {
  var2 -> b[i] = i;
}

free(var2);

上面结构体的第二个成员变量b[0]事实上是不占内存空间的,因此sizeof(struct test2)结果为4。如上所示,通过malloc()申请了一段长度为结构体长度加可变长度(LENGTH)的内存空间给结构体类型的指针,b[0]就指向可变长度的内存空间。此段内存空间是连续的。
其实只要是数组,其分配的内存空间就是连续的,并且也是只需要分配一次内存空间。

struct test3 {
  int a;
  int b[1];
} __attribute((packed));

printf("the length of struct test3:%d\n", sizeof(struct test3)); //结果为8

struct test3 *var3;
var3 = (struct test3 *)malloc(sizeof(struct test3));
var3 -> a = 3;
(var3 -> b)[0] = 3; //暂时不知括号何用???

free(var3); //只需释放一次

个人认为,使用长度为0的数组的好处是:其可变长度(LENGTH)可以由不同地方的代码共同决定。

参考链接:http://blog.csdn.net/zhaqiwen/article/details/7904515

你可能感兴趣的:(长度为0的数组)