2012-04-03 8 views
1

Как использовать аргументы функции для объявления массива внутри функции?Объявление массива в C

Мой код:

double function_2(int a) 
{ 
    int t[a]; 
} 

возникает ошибка:

Expression must have a constant value. 
+0

возможный дубликат [Инициализация массива после заявления] (http://stackoverflow.com/questions/2816765/initializing-an -array-after-declaration) – mdm

+0

Вы уверены, что используете компилятор C? Обратите внимание, что массивы переменной длины являются расширениями GNU до C99. –

+0

@mdm: Это не обязательно дубликат. Другие ответы на связанный с вами вопрос предлагают только динамическое распределение, потому что в нем явно указано C89, где не существует понятия массивов переменной длины. –

ответ

1

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

В противном случае используйте понятие указателя.

1

Вместо массива вы должны использовать распределение памяти и использовать его как массив для итерации или другого использования.

6

Ваш код является полностью действующим кодом C.

Вы используете VLA (массив переменной длины). Это функция c99, и вам нужно обеспечить, чтобы ваш компилятор поддерживал код c99.

Если вы используете gcc, по умолчанию gcc установлен в -std=gnu89, который является расширениями C89 + GNU. Используйте -std=c99 или -std=gnu99 с gcc, чтобы скомпилировать вашу программу.

Если вы используете MSVC, к сожалению, он не поддерживает c99, поэтому вы не можете использовать функцию c99 с этим компилятором.

EDIT:

Если ваш компилятор не поддерживает VLA вы можете использовать динамическое выделение памяти вместо:

#include <stdlib.h> 

double function_2(int a) 
{ 
    // Allocate array object 
    int *t = malloc(a * sizeof *t); 

    if (!t) { 
     // Handle malloc errors 
    } 

    // Write your program here: ... 

    // Free array object 
    free(t); 
} 
+1

Хотя это правильно, вы также должны предоставить решение (динамическая память с использованием 'malloc' или больше похожа на VLA, используя' alloca' для резервирования памяти стека). Это сделало бы его идеальным ответом :) –

+0

@NiklasB. Я согласен, что информация о 'malloc' актуальна, и я добавляю ее. Что касается 'alloca', это стандартная функция non C. – ouah

+0

Да, но я думаю, что он может быть использован в качестве обходного пути в MSVC, который использует OP. –

2

C99 имеет расширение для variable length arrays. При компиляции кода с помощью следующей команды, он будет работать:

gcc -std=gnu99 lala.c -o lala 

Если вы используете VC++, массивы переменной длины нет, так как стандарт использует это C89 с некоторыми особенностями C99 (не включая переменные длина массивов).


Поскольку вы упоминаете компиляции с VC++ я добавлю несколько замечаний:

  • Убедитесь код компилируется в C путем изменения расширения исходных файлов, чтобы быть .c вместо .cpp
  • Поскольку массивы переменной длины не поддерживаются, как я сказал ранее, вам придется использовать динамический подход (см. Ниже).

Использование динамического распределения, чтобы сделать эквивалент того, что вы пытаетесь:

int * t = malloc(a * sizeof(int)) 

Если вы используете динамическое распределение и хотите вернуть массив, вы можете сделать это за счет того, возвращаем функцию int *, а затем возвращаем t.Однако, если вы это делаете, это также возвращает длину массива (если только это не фиксированная известная длина). Общие методы, используемые для возврата этой длины:

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

Например:

// Returns number of entries in the Lala array returned from b() 
int GetNumLalaEntries(void); 

// Function b which returns an array. 
int * b(void) 
{ 
    int * lala = malloc(5 * sizeof(int *)); 
    ... 
    return lala; 
} 

В приведенном выше случае, GetNumLalaEntries возвращает 5 всегда, но если это число было динамичным, что необходимо будет генерироваться из некоторой внутренней информации синхронизации.

  • Используйте первую технику и передайте проход вызывающего в массиве. Оптимальная вещь заключается в том, что вызывающий объект имеет дело с распределением и освобождением массива.

Например:

// We are passing in the array this time. 
void b(int * lala) 
{ 
    ... // Do whatever you need with lala 
} 

int main(void) 
{ 
    int * lala = malloc(GetNumLalaEntries() * sizeof(int *)); 
    b(lala); 
    return 0; 
} 
  • возвращающая struct вместо которого как указатель массива и размер массива.

Например:

struct lala_encapsulation { 
    int * lala; 
    int lala_entries; 
}; 

struct lala_encapsulation b(void) 
{ 
    struct lala_encapsulation le; 
    le.lala_entries = 5; 
    le.lala   = malloc(le.lala_entires * sizeof(int *)); 

    return le; 
} 

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

+0

Спасибо, я следил за комментариями. Вопрос: если возвращаемый тип функции является массивом, как я могу использовать * t (указатель) для возврата массива t? – holy

+0

@holy: Отредактировал мой ответ, чтобы включить возвращаемый массив. –

+0

: Это часть моего кода: JNIEXPORT jintArray JNICALL Java_MainClass_intArrayMethod (JNIEnv * env, jobject obj, jfloatArray array, jint nb_of_subscribers, jint tags) {jsize len = (* env) -> GetArrayLength (env, array); jint * body = (* env) -> GetIntArrayElements (env, array, 0), после чего я сделал некоторые изменения в body [], и я хочу вернуть все данные, указанные телом. Есть ли способ сделать это? – holy

1
double function_2(int a) 
{ 
    int * t = (int*)malloc(sizeof(int)*a); 
    for(int i = 0; i<a; i++) 
    { 
    // do your work here, accessing t like an array 
    t[i]=... 
    } 
    free(t); 

... 
} 
+0

Идея правильная, но 'i

+0

Вы правы. Добавлена ​​коррекция. – Flynch

+0

Спасибо, я следил за комментариями. Вопрос: если возвращаемый тип функции является массивом, как я могу использовать * t (указатель) для возврата массива t? – holy

1

Вы должны использовать кучу (таНос/бесплатно)

#include<stdlib.h> 

double function_2(int a) 
{ 
.... 
    int *t = (int*) malloc (sizeof(int) *a); 
    t [1] = 1; // but check if array is large enough 
    ... 
    free (t); 
    ... 
    return 0.0; 
} 
+0

Несмотря на то, что вы разочарованы и устарели, вы все равно можете использовать стек для распределений по размеру с помощью ['alloca'] (http://www.gnu.org/software/libc/manual/html_node/Advantages-of-Alloca.html), когда VLA не поддерживаются. –

Смежные вопросы