parameter - variable length array c++




Что означает « (2)

Какова его цель, почему она была добавлена?

Цель видна, когда двумерный массив переменной длины используется в качестве параметра функции. Функция

int foo(int n, int m, int a[n][m])  {...}   

может быть прототипирован как любой из следующих

int foo(int , int, int [][*]);
int foo(int , int, int a[*][*]);
int foo(int , int, int (*a)[*]);
int foo(int n, int, int a[n][*]);
int foo(int , int m, int a[*][m]);
int foo(int , int m, int (*a)[m]);
int foo(int n, int m, int a[n][m]); 

В случае двумерного массива, при использовании в качестве параметра функции, размер второго измерения не может быть опущен. Если имя первых переменных в прототипе функции опущено, тогда будет невозможно указать длину (второе измерение) массива. Знак * дает понять, что длина массива будет определяться вторым параметром.

Какая разница с int[] ?
Какая разница с int * ?

В случае 1D массива, для определения функции

int bar(int n, int a[n]} {...}  

любой из следующих прототипов действителен

int bar (int , int *);
int bar (int , int [*]);
Int bar (int , int []);
int bar (int n, int a[]);
int bar (int n, int a[n]);
int bar (int n, int [n]);   

В этом случае ни * ни n не требуется, так как компилятор будет обрабатывать как int [*] и int [n] как int * . Итак, с одномерным массивом вы не видите большой разницы.

ПРИМЕЧАНИЕ. При использовании массива переменной длины в качестве параметра функции важен порядок параметров. Порядок параметров для первых четырех прототипов bar можно переключать, но в последних двух первых параметрах не должен быть сам массив.

int bar (int a[n], int n);  //Wrong. Compiler has not yet seen 'n'.

Пытаясь реализовать синтаксический анализатор C11 (для образовательных целей), я обнаружил, что в C11 (стр. 470), а также в C99 (стр. 412) (спасибо Иоганнесу!) Прямой декларатор определяется как:

(6.7.6) direct-declarator:  
    direct-declarator [ type-qualifier-list? * ]

Сначала я думал, что это ошибка в грамматике (список типов не должен быть необязательным). Однако, когда я попробовал это в моем компиляторе ссылок (clang), я получил довольно неожиданную ошибку:

int array[*] = { 1, 2, 3 };
// error: star modifier used outside of function prototype

Таким образом, по-видимому, (в clang) это называется модификатором звезды .

Я быстро понял, что они могут использоваться только в сигнатурах функций:

void foobar(int array[*])

Однако они могут использоваться только в декларации. Попытка использовать его в определении функции также приводит к ошибке:

void foobar(int array[*]) {
    // variable length array must be bound in function definition
}

Итак, насколько я могу судить, предполагаемое поведение - использовать [*] в объявлении функции, а затем использовать фиксированное число в определении функции.

// public header
void foobar(int array[*]);

// private implementation
void foobar(int array[5]) {

}

Тем не менее, я никогда не видел это, и я не совсем понимаю цель этого тоже.

  1. Какова его цель, почему она была добавлена?
  2. Какая разница с int[] ?
  3. Какая разница с int * ?

Обоснование документа C99 говорит

Прототип функции может иметь параметры, которые имеют типы массивов переменной длины (§6.7.5.2), используя специальный синтаксис, как в

int minimum(int, int [*][*]);

Это согласуется с другими прототипами C, в которых имя параметра указывать не нужно.

Какая разница с int []

Какая разница с int *.

Я думаю, просто, что эти типы в прототипе функции означают «указатель», в то время как [*] в не верхней позиции ( int[*] прежнему равно int[] я думаю, в прототипе функции) на самом деле является допустимым и означает массив

// not recommended though: it is now unclear what the parameters
// mean to human callers!
void f(int, int [][*]);

void f(int n, int x[][n]) {
    x[1][0] = 1;
}

int main() {
   int a[2][1];
   f(1, a);
   printf("%d\n", a[1][0]);
}

Что касается цели, при индексации массива в определении функции компилятору необходимо знать, сколько целых чисел следующего индекса пропустить при задании первого индекса ( x[i] пропускает i * n целых чисел в f выше). Но эта информация не требуется в объявлении неопределяемого прототипа, поэтому ее можно опустить и заменить на * .





variable-length-array