Как использовать `static` с массивом массивов в C

Данный,

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]?

Все размеры, кроме самого левого, должны быть определены. Размеры могут быть определены статически, например. [6], или может быть определено по-разному, например. [cols] при условии, что выражение cols можно вычислить и реализация поддерживает указатели на массивы переменной длины.

Ian Abbott 08.07.2024 19:58

В данном контексте static означает «по крайней мере». Компилятор не может вычислить адрес arr[1], если он не знает, насколько велик arr[0]. Что-то вроде «хотя бы xy байт» здесь бесполезно.

Gerhardh 09.07.2024 11:32
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
0
2
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В параметре, объявленном как массив массивов, стандарт 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 08.07.2024 20:07

@gberth: Это «по крайней мере». В C 2018 6.7.6.3 7 говорится: «… Если ключевое слово static также появляется в [ и ] вывода типа массива, то для каждого вызова функции значение соответствующего фактического аргумента должно обеспечивать доступ к первому элементу массива. массив, содержащий как минимум столько элементов, сколько указано в выражении размера».

Eric Postpischil 08.07.2024 20:21

Интересный; это нюанс, который я упустил. Интересно, как clang и GCC справляются с этим, когда дело доходит до статического анализа. Еще раз спасибо Эрик!

gberth 08.07.2024 20:58

Другие вопросы по теме