Передача по ссылке 3-Dim Массив фиксированной длины - PullRequest
2 голосов
/ 28 ноября 2010

Может кто-нибудь намекнуть, как передать по ссылке массив вида

int array[2][3][4];

, чтобы я мог сохранить его указатель для использования и изменения массива?Например, если бы я говорил об одном целом числе:

// Scope 1
int a = 3;
increment(&a);
// End Scope 1

// Scope 2
int *pa;
void increment(int *tpa) { 
  pa = tpa; *pa++; 
}
// End Scope 2

Большое спасибо и наилучшие пожелания.

Ответы [ 4 ]

8 голосов
/ 28 ноября 2010

Если вы действительно хотите передать массив по ссылке, вы можете сделать это:

void f(int (&a)[2][3][4]) { }

В C, который не имеет ссылок, вы можете передавать массив по указателю (конечно, это работает и в C ++):

void f(int (*a)[2][3][4]) { }
3 голосов
/ 28 ноября 2010

C ++:

void f(int (&array)[2][3][4])
{
}

C: в C

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

void f(int array[][3][4])
{
}
2 голосов
/ 29 ноября 2010

Спасибо всем, кто участвовал в этом!sskuce предоставил очень хорошее решение, используя преимущества «контейнера».Я думал об этом, но мне не нравились дополнительные вещи.После небольшого недоумения я понял, что Джеймс Макнеллис всегда давал ответ.Итак ... вот решение, которое я предпочитаю без контейнеров и арифметики индексов (обратите внимание на круглые скобки):

void Scope1() 
{
    int array[2][3][4];
    Scope2(&array);
}

int (*pArray)[2][3][4];

void Scope2(int (*tpArray)[2][3][4])) 
{
    pArray = tpArray;
    (*pArray)[0][0][0] = 3;
}

Еще раз спасибо всем.

1 голос
/ 28 ноября 2010

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

Инкапсулирует массив в структуре, например,

typedef struct ArrayHolderStruct{
    int array[2][3][4];
} ArrayHolder

//...
//scope 1
ArrayHolder thingy;
thingy.array[0] = something;
//other initialization.
F( &thingy );
//...

//scope 2
ArrayHolder *pa;
void F ( ArrayHolder *p ){
    pa = p;
    p->array[0][1][2] = 42;
}

//Call F first to set pa.
void G(){
    pa->array[0][1][2] = 6 * 9; // if pa = &thingy, thingy will be modified.
}

Структура позволит вам сохранить информацию о компоновке инкапсулированного массива, и вам не придется беспокоиться о мерзкой индексной арифметике.

----- СТАРЫЙ ОТВЕТ ----- Передача ссылки на массив бесполезна, если только вы не хотите изменить размер или компоновку массива (что в любом случае вы не можете сделать с массивами статического размера). Вы получите ссылку (или указатель) на элементы массива, даже если вы передадите массив по значению. То есть, если вы объявите свою функцию:

void f ( int a[2][3][4] ){
    a[0][1][2] = 42;
}

и вызывать его как f( array ) при выходе из f, array[0][2][2] будет установлен на 42, даже если вы не передали "ссылку" на array в функцию.

Если вы хотите сохранить указатель на массив для последующего использования в функции библиотеки и т. Д., Вы можете сделать что-то вроде:

//scope 2
int * pa;
void f ( int a[2][3][4] ){
    pa = &a[0][0][0];
}

В этот момент становится сложно - вы должны знать, как pa выкладывается (выкладывается?) В память. Я думаю, что C стандартизировал 'мажорный порядок строк', поэтому массив должен быть расположен в памяти как:

a[0][0][0] a[0][0][1] a[0][0][2] a[0][0][3] a[0][1][0] ... a[0][2][3] a[1][0][0] a[1][0][1]... a[1][2][3]

Итак, чтобы получить элемент с индексом [n][j][k], вам нужно сделать что-то вроде:

pa[n * 12 + j * 4 + k] = something;

По сути, умножьте каждый индекс на количество элементов, на которые может ссылаться индекс этого порядка, например, каждый индекс k указывает ровно на один элемент с фиксированным индексом j и n, каждый индекс j может указывать на 4 элемента с фиксированным индексом n, а каждый индекс n может указывать на один из 12 (потому что 12 = 3 * 4) элементов.

Как я уже сказал, это сложно. См. Статьи в Википедии о структурах массивов данных и мажорном порядке , чтобы лучше понять, как устроены эти вещи.

...