Прототип для массивов переменной длины - PullRequest
6 голосов
/ 29 августа 2011

Я пытаюсь написать функцию, которая принимает массив переменного размера в c.

void sort(int s, int e, int arr[*]){
    ...
}

В нем говорится, что для массивов переменной длины он должен быть ограничен в объявлении функции.Что это значит?Я использую xcode 4.0, с компилятором LLVM 2.0.

Спасибо за помощь.

Ответы [ 4 ]

23 голосов
/ 29 августа 2011

Поскольку я вижу, что никто не отвечает на настоящий вопрос, здесь я задаю мой.

В C99 у вас есть массивы переменной длины (VLA), которые объявляются с длиной, которая оценивается во время выполнения, а не только во время компиляции, как в предыдущих версиях C. Но передача массивов в функции немного сложна.

Одномерный массив всегда просто передается как указатель, поэтому

void sort(size_t n, int arr[n]) {

}

эквивалентно

void sort(size_t n, int *arr){

}

Более высокие измерения хорошо переданы функции

void toto(size_t n, size_t m, int arr[n][m]){

}

эквивалентно

void toto(size_t n, size_t m, int (*arr)[m]){

}

При таком определении внутри такой функции вы можете получить доступ к элементам с выражениями, такими как arr[i][j], и компилятор знает, как вычислить правильный элемент.

Теперь приходит синтаксис, который вы обнаружили, который полезен только для прототипов , то есть мест, где вы заранее объявляете интерфейс функции

void toto(size_t, size_t, int arr[*][*]);

поэтому здесь вы можете заменить размер массива на * в качестве заполнителей. Но это полезно только тогда, когда у вас нет названий размеров под рукой, и гораздо понятнее использовать точно такую ​​же версию, что и для определения.

void toto(size_t n, size_t m, int arr[n][m]);

Как правило, для последовательного использования важно, чтобы в списке параметров сначала были размеры. В противном случае они не будут известны, когда компилятор анализирует объявление arr.

2 голосов
/ 29 августа 2011

Если вы не используете массивы переменной длины C99, обычное решение - передать указатель на первый элемент вместе с любыми индексами, которые вы хотите использовать для доступа к элементам.

Вот фрагмент кода, который распечатывает диапазон массива, аналогично тому, что вы пытаетесь сделать с вашим sort.

#include <stdio.h>

static void fn (int *arr, size_t start, size_t end) {
    size_t idx;
    for (idx = start; idx <= end; idx++) {
        printf ("%d ", arr[idx]);
    }
    putchar ('\n');
}

int main (void) {
    int my_array[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
    fn (my_array, 4, 6);
    return 0;
}

Это выводит элементы с четвертого по шестой включительно (с нуля), давая:

5 4 3

Несколько замечаний.

  • Использование my_array в вызове этой функции для fn автоматически «разлагает» массив на указатель на его первый элемент. На самом деле это происходит в большинстве (не во всех) случаях, когда вы используете массивы, поэтому вам не нужно явно указывать &(my_array[0]).

  • C уже имеет очень хорошую функцию сортировки, встроенную в стандартную библиотеку, которая называется qsort. Во многих случаях это то, что вам следует использовать (если только у вас нет определенного алгоритма, который вы хотите использовать для сортировки, или вы делаете домашнее задание / упражнение на самообразование).

2 голосов
/ 29 августа 2011

То, что вы хотите сделать, делает ваш аргумент int *;передать длину массива (который, по-видимому, знает вызывающая сторона, но эта подпрограмма не знает) как отдельный аргументВы можете передать массив в качестве такого аргумента.

1 голос
/ 22 июля 2015

Использование * внутри скобок массива для массивов переменной длины ограничено прототипами и служит просто заполнителем.Когда функция будет определена позже, размер массива должен быть сохранен в переменной, доступной либо в области файла, либо в качестве одного из параметров.Вот простой пример:

void foo(int, int[*]);
/* asterisk is placeholder */

void foo(int size, int array[size]) {
/* note size of array is specified now */
}
...