2013-08-08 2 views
1

Возможно ли инициализировать объект с переменным размером, например struct IP_addresses ip_addr[no_of_users] below?Как инициализировать объект с переменным размером

void foo(int no_of_users){ 
    struct IP_addresses{ 
     char IPaddr[16]; 
    }; 
    struct IP_addresses ip_addr[no_of_users]; 
    //..... 
} 

int main(void){ 
    int no_of_users = 4; 
    foo(no_of_users); 

    return 0; 
} 
+0

Я не думаю, что ваш код будет даже скомпилировать – user2408578

+1

@ user2408578: Он компилирует. C 1999 добавлены массивы переменной длины. –

+1

Вы пытались скомпилировать его, возникают ли у вас проблемы? Я предполагаю, что вы сначала попробовали код, прежде чем отправлять вопрос здесь. – Nobilis

ответ

3

Вы не можете инициализировать массивы переменной длины. От C 2011 (N1570) 6.7.9, «Инициализация», пункт 3:

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

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

+1

Вы уверены, что я просто протестировал его на gcc 3.4.4./cygwin, и он отлично работает. – Devolus

+0

Это правда, но я думаю, что название вопроса просто неверно. OP может или не может на самом деле просить об инициализации. Это еще не определено. – brianmearns

+0

@Devolus: Это прямая цитата из проекта N1570 стандарта ISO/IEC C. –

-1

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

Вы должны использовать динамическое распределение (malloc и free).

+0

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

2

Если то, что вы имели в виду это выделить/объявить переменную размера объектов, то да в современных компиляторов, это возможно для локальных динамических переменных. Это связано с тем, что все компиляторы должны делать это, это bump указатель стека, чтобы освободить место для ваших локальных варов, когда он входит в функцию, поэтому к этому времени он знает значение параметра no_of_users.

Как правило, не переменные, поскольку они не живут в стеке и настроены до вызова функции.

Он также не будет работать для любых переменных, которые компилятор должен выделить, если во время компиляции не известно, сколько их нужно выделить. Например:

static unsigned int no_of_users = 10; 
static char var[no_of_users]; 

int main(void){ 
    return 0; 
} 

не будет работать, но это будет:

#define no_of_users 10 

static char var[no_of_users]; 

int main(void){ 
    return 0; 
} 
+2

Вопрос не спрашивает, можете ли вы определить массив переменной длины. Он спрашивает, можете ли вы его инициализировать. Вы можете определить массив переменной длины. Вы не можете его инициализировать. –

+0

Хорошая точка. Я взял из примера кода OP то, что на самом деле означало объявление объявления массива переменной длины, и OP просто не знал, что существует разница. Мы должны увидеть, что на самом деле означало. – brianmearns

1

Собран с GCC 3.4.4 работает отлично.

Однако он работает, потому что это локальная переменная в стеке. Как отметил sh1ftst0rm, он не будет работать со статическими/глобальными переменными.

#include <stdio.h> 
#include <stdlib.h> 

void tester(int n) 
{ 
    int sz[n]; 
    int i; 
    for(i = 0; i < n; i++) 
     sz[i] = 0; 
} 

int main() 
{ 
    tester(5); 

    return 0; 
} 
1

Следующий код компилируется и работает с gcc 4.4.5.

#include <stdlib.h> 
#include <stdio.h> 

void foo(int no_of_users) 
{ 
    struct IP_addresses 
    { 
     char IPaddr[16]; 
    }; 
    struct IP_addresses ip_addr[no_of_users]; 
    int i; 

    for(i = 0; i < no_of_users; i ++) 
     sprintf(ip_addr[i].IPaddr, "test%02d", i); 

    for(i = 0; i < no_of_users; i ++) 
     printf("%s\n", ip_addr[i].IPaddr); 
} 

int main(int argc, char **argv) 
{ 
    int i, no_of_users; 

    for(i = 1; i < argc; i ++) 
    { 
     no_of_users = strtol(argv[i], 0, 10); 
     foo(no_of_users); 
    } 

    return 0; 
} 

Я не уверен, что говорят эти стандарты, но на практике это просто работает. Вот что я получил в качестве результатов:

$ gcc -o ./test ./test.c 
$ ./test 3 4 5 
test00 
test01 
test02 
test00 
test01 
test02 
test03 
test00 
test01 
test02 
test03 
test04