Я переживаю всплеск интереса к системе с переменным изменением типа 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
, не делая ни одного актера и даже включаете все предупреждения! Или я что-то упускаю?