【发布时间】:2015-04-19 21:31:24
【问题描述】:
我对 C99 的可变修改类型系统产生了浓厚的兴趣。这个问题的灵感来自this one。
检查这个问题的代码,我发现了一些有趣的东西。考虑这段代码:
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 严格检查数组的大小,也可以轻松地进行越界数组写入,不进行一次强制转换,甚至打开所有警告!还是我错过了什么?
【问题讨论】:
-
如果您还没有,请尝试将 -std=c99 -pedantic-errors 添加到您的 gcc 编译行,看看是否有任何不同。
-
@jschultz410: 好主意,但不——它根本没有区别 =(
-
在很多情况下编译器不可能静态推断出 c 的值(例如 - c 是从标准输入输入的)。因此,通常不可能对此类函数定义的参数进行任何有意义的静态类型检查。如果你这样做,编译器会说“好的,我允许你传递任何你想要的 d,只要它的类型是一个双索引整数数组。祝你好运!”
-
在这样的函数中,对于具有不同 c 值的不同调用会发生什么?它是否通过基于 c 动态计算它应该在内存中前进多远来做正确的事情?
-
@jschultz410:我不确定我理解你的意思......你能举个例子吗?
标签: c gcc c99 variable-length-array