我对C99的可变修饰类型系统产生了浓厚的兴趣。这个问题是受到这篇文章的启发。
查看这个问题的代码,我发现了一些有趣的东西。考虑下面的代码:
int myFunc(int, int, int, int[][100]);
int myFunc(int a, int b, int c, int d[][200]) {
/* Some code here... */
}
这段代码明显不能编译(也确实没有编译)。然而,下面这段代码:
int myFunc(int, int, int, int[][100]);
int myFunc(int a, int b, int c, int d[][c]) {
/* Some code here... */
}
在gcc编译时,甚至没有警告。
这似乎意味着可变修改的数组类型与任何非可变修改的数组类型都兼容!
但这还不是全部。你会期望可变修改的类型至少会关心使用哪个变量来设置其大小。但它似乎并没有这样做!
int myFunc(int, int b, int, int[][b]);
int myFunc(int a, int b, int c, int d[][c]) {
return 0;
}
同时编译没有任何错误。
所以,我的问题是:这种行为是否正确标准化了?
另外,如果一个可变修改的数组类型确实与具有相同维度的任何数组兼容,这是否意味着存在恶意安全问题?例如,请考虑以下代码:
int myFunc(int a, int b, int c, int d[][c]) {
printf("%d\n", sizeof(*d) / sizeof((*d)[0]));
return 0;
}
int main(){
int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
myFunc(0, 0, 100, &arr);
return 0;
}
编译并输出100,没有错误或警告,什么都没有。在我看来,这意味着轻松越界写入数组,即使您通过sizeof
严格检查数组的大小,不进行任何转换,甚至打开所有警告!还是我漏掉了些什么?