所谓编译时可变长数组,就是这种:
struct record {
char *name;
int age;
};
struct record g_records1[] = {
{"wangchunyu", 25},
{"arteezy", 26},
};
int main() {
for (int i = 0; i < sizeof(g_records1)/sizeof(struct record); i++) {
printf("player name %s, age %u\n", g_records1[i].name, g_records1[i].age);
}
return 0;
}
或者这种
struct record g_records2[] = {
{"wangchunyu", 25},
{"arteezy", 26},
{NULL, 0},
};
int main() {
int i = 0;
while (g_records2[i].name) {
printf("player name %s, age %u\n", g_records2[i].name, g_records2[i].age);
i++;
}
return 0;
}
方式1通过数组总size除以数组元素的size,动态算出元素数目,这就是可变长数组,又因为那两个size都是编译时可确定的,所以叫做编译时可变长数组
方式2通过检查数组元素的某个字段是否为空来确定退出条件,同时也就确定了元素数目,这也是编译时可变长数组的一种实现。
上面两种方式确定数组元素数目,都要通过计算得出,那有没有不需要计算的方式呢?有的
enum dota_carrys {
WANG_CHUN_YU = 0,
ARTEEZY,
CARRY_NUM,
};
struct record g_records3[CARRY_NUM] = {
{"wangchunyu", 25},
{"arteezy", 26},
};
int main() {
for (i = 0; i < CARRY_NUM; i++) {
printf("player name %s, age %u\n", g_records3[i].name, g_records3[i].age);
}
return 0;
}
方式3定义了一个枚举类型,并将第一个枚举值固定为0,这样后面增加的枚举值就起到了数组下标的作用——因为枚举值也是编译时可确定的。
注意最后一个枚举值无实际意义,仅起到标记枚举值总数
的目的——因为枚举值默认自增,最后一个item_index加1,就是item_num嘛。
var_arr.c:28:5: warning: excess elements in array initializer
{"xinq", 24},
^
var_arr.c:28:5: note: (near initialization for ‘g_records3’)
枚举方式跟方式1比,在性能上没有区别,在表示法上更灵活些,但维护起来也更麻烦些。
枚举方式跟方式2比,性能上可能会好点,而且不用担心数组内容被踩时访问越界,但方式2可用于运行时可变长数组,适用范围更广。