这是在一次研讨会中发现的我知识上的纰漏,在此进行记录。
当时想给学弟学妹讲一下关于动态内存的问题,在讲述时我用了一个初始化变量时不能用变量作为下标。例如:
int i = 5;
char test[i];
然而事实上,在这样写了之后我发现编译没有出错,这和我最开始学C语言时老师给我们讲的内容并不相同。我最初怀疑时因为此时i已经被赋值了而后在此期间没有进行计算,所以编译器可能将其直接作为一个宏定义来解析了。但是我们又尝试了如下两种写法。
int i = 5;
i++;
char test[i];
int i;
scanf("%d", &i);
char test[i];
此时编译器仍然没有报错,而且生成的程序运行起来也是正常的。故而这样的写法其实是正确的,其运行逻辑应该是这种语句在被编译的时候成为了类似于malloc的语句,同时在后面的某个位置自动添加了free,不过因为我对汇编并不是特别熟,只能从理论层面大概分析一下,具体内容各位可以使用反汇编自行查看。
不过需要注意的是,在定义的时候不能直接赋值:
int i = 5;
char test[i] = {0, 1, 2, 3, 4};
原因可能在于等号赋值是先右后左,虽然在普通直接使用常量定义数组的时候没有关系,但那应该是在编译状态就可以计算出的内容,只要赋值的长度不超就没事,而这种变量赋值则类似于一种动态分配,编译器并不能预测在运行时这个变量究竟是多少,哪怕你知道它只能是这么多,但是编译器并没有那么智能,不如就直接报错处理了。
考虑到最开始学到这个知识的时候老师讲课用的书是谭浩强的那本,限于时代因素那本书使用的C语言标准应该是在C89左右,而当时实验课我们使用DEV-C++进行编译也会遇到这种问题,故而我怀疑可能在C99或者C11的版本中发生了某种改变,毕竟我现在用的是C11的gcc了。不过具体是什么时候不重要,记住这个结论就好了。
另外我真认为各高校确实该换本教科书了……