Данный,
int last(int arr[3][6]) {
return arr[2][5];
}
Я хочу прояснить, что arr не может иметь значение null с ключевым словом static.
Проблема в том, что следующий код не будет работать.
int last(int arr[static 3][static 6]) {
return arr[2][5];
}
Используя gcc13 -std=c2x я получаю:
error: static or type qualifiers in non-parameter array declarator
Почему я могу сделать arr[static 3][6], а не arr[static 3][static 6]?
В данном контексте static означает «по крайней мере». Компилятор не может вычислить адрес arr[1], если он не знает, насколько велик arr[0]. Что-то вроде «хотя бы xy байт» здесь бесполезно.



В параметре, объявленном как массив массивов, стандарт C определяет static только в первом измерении, и это единственное измерение, в котором он вам нужен.
C 2018 6.7.6.2 1 говорит:
… Необязательные квалификаторы типа и ключевое слово static должны появляться только в объявлении параметра функции с типом массива, а затем только в самом внешнем производном типе массива.
static полезен, потому что в противном случае самое внешнее измерение было бы потеряно. Объявление параметра int a[3][6] автоматически изменяется на int (*a)[6], который является указателем на массив из 6 int, но нет информации о том, сколько массивов из 6 int находится в этом месте.
int a[static 3][6] также корректируется на int (*a)[6], но с дополнительной информацией о том, что в этом месте должно быть как минимум 3 массива по 6 int.
Во втором измерении нет необходимости в static, поскольку информация о втором измерении не теряется. int [6] — полный тип; это массив из 6 int. Если у нас есть указатель на один массив из 6 int, там их 6 int. Если у нас есть указатель на три массива по 6 int, то там будет 3 массива по 6 int (всего 18 int).
Спасибо, это именно то, что я искал. Дополнительный вопрос: в своем ответе вы написали should be at least 3 arrays of 6 int at that location, это действительно «минимум 3» или вы имели в виду «ровно 3»?
@gberth: Это «по крайней мере». В C 2018 6.7.6.3 7 говорится: «… Если ключевое слово static также появляется в [ и ] вывода типа массива, то для каждого вызова функции значение соответствующего фактического аргумента должно обеспечивать доступ к первому элементу массива. массив, содержащий как минимум столько элементов, сколько указано в выражении размера».
Интересный; это нюанс, который я упустил. Интересно, как clang и GCC справляются с этим, когда дело доходит до статического анализа. Еще раз спасибо Эрик!
Все размеры, кроме самого левого, должны быть определены. Размеры могут быть определены статически, например.
[6], или может быть определено по-разному, например.[cols]при условии, что выражениеcolsможно вычислить и реализация поддерживает указатели на массивы переменной длины.