2014-10-14 8 views
-1

Может ли статический массив, объявленный в main, инициализироваться/мутировать в функции?Инициализация статического массива в функции в C

Я пробовал код ниже, но он возвращает ошибку seg.

void initialize(int **p, int a, int b) 
{ 
    int i, j; 
    for(i=0; i<a; ++i) { 
     for(j=0; j<b; ++j) 
      p[i][j] = j; 
    } 
} 

int m = 5; 
int n = 5; 
int arr[m][n]; 
int **A = &arr[0][0]; 


initialize(A, m, n); 

EDIT:

Я нашел хорошее объяснение этого вопроса здесь:

http://c-faq.com/aryptr/pass2dary.html

+1

'A' is ** not **' int ** 'То, что вы сказали, что они были синонимами, неверно. – WhozCraig

+0

Этот код не должен компилироваться: http://ideone.com/OCCB95. –

+1

@WhozCraig. Я редактировал код.Я фактически создал двойной указатель на статический массив. – Ares

ответ

2

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

void initialize(int a, int b , int p[][b]) 
{ 
    ... 

Поскольку вы должны определить размер для массива p, аргументы a и b объявлены первые, а затем b используются для определения размера.

+0

Что делать, если я объявляю и инициализирую двойной указатель на статический массив? – Ares

+2

@ Zaphod перестает думать, что указатель на указатель является синонимом массива массивов. Они не то же самое. Рассматривая указатель, считайте его «указателем на последовательность X», где X - тип указателя. Поэтому указатель на указатель является «указателем на последовательность ** указателей **». Тип arr [n] [m] 'не является такой последовательностью. Этот ответ является одним из правильных способов передачи массива массивов в функцию. В вашем вопросе 'arr' представляет собой массив массивов. Это делает * not * выражать как указатель на указатель при передаче функции, и, как я уже сказал, однако вы пришли к выводу, что они были синонимами, это просто неправильно. – WhozCraig

+1

@ 2501 Если я хочу, могу ли я сделать 'int p [a] [b]' вместо 'int p [] [b]'? Почему последний? – Ares

0

Изменение

initialize(A, m, n); 
void initialize(int **p, int a, int b) 

в

initialize(n, A, m); 
void initialize(int b, int p[][b], int a) 

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

+4

не делайте этого, так как он предполагает, что b всегда 5. – gsamaras

+0

@ G.Samaras: Вы правы, я видел, что OP инициализировал его до 5 так, чтобы второе измерение было «5». – user1336087

+1

Я подозревал, что вы это сделали. Сделанное вами редактирование не будет компилироваться, так как b не известно. (вот почему у вас есть -1 от кого-то). – gsamaras

1

Включить предупреждения в вашем компиляторе, и вы получите это:

warning: passing argument 1 of ‘initialize’ from incompatible pointer type [enabled by default] 

В результате вы получите SEG. неисправность.

Вы должны изменить прототип вашей функции к этому:

void initialize(int a, int b, int p[][b]); 

и вызов функции будет:

initialize(m, n, A); 
+1

Вызов функции также изменится :) – user1336087

+1

ОП указывает, что он объявляет 'A' внутри' main', поэтому он не является статичным. Кроме того, VLA * не может быть объявлен статическим или в области файлов. –

+0

Пропустил это @JohnBode! Спасибо вам, обновил мой ответ. :) – gsamaras

1

Да, они могут, не было бы очень полезно если бы они не могли.

Однако вы столкнулись с проблемой, связанной с тем, как вы пытаетесь разложить массивы на указатели. То, что вы объявили в main, является двумерным массивом - единым блоком памяти, который, как оказалось, индексируется через комбинацию из двух индексов (переведенных во время компиляции). Вы пытаетесь разложить его так, как если бы это был массив указателей для массивов, что означает, что в пределах initialize вы разыгрываете указатель, чтобы попытаться получить указатель, а затем разыменовываете это, чтобы получить слот. Так как двумерный массив на самом деле описывает один блок памяти, два слоя указателя не будут работать для его доступа. Вам нужно разложить его на тип, включающий только один уровень указателя.

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