Есть ли способ иметь один массив, который содержит другие массивы в c? - PullRequest
1 голос
/ 17 сентября 2011

У меня есть 4 массива int.Все они имеют одинаковое количество элементов.Примерно так:

int  ar1[] = {1,2,3,4};
int  ar2[] = {10,12,13,14};
int  ar3[] = {8,9,15,16};
int  ar4[] = {17,18,19,20};
int  big[][] ={ar1,ar2,ar3,ar4};  // I know this is messed up but here is where the question lies

Есть ли способ, чтобы при запуске цикла for:

int i;
for(i =0; i<4; i++){
    int x;
    for(x = 0; x<4; x++){
       printf(big[i][x]); // something like this   
    }
}

Чтобы при выполнении он выводил:1008 * Массив 1: 1 2 3 4 Массив 2: 10 12 13 14 и т. Д. *

Спасибо.

Ответы [ 4 ]

3 голосов
/ 17 сентября 2011

Проверьте это: Многомерные массивы в C и на этой странице Википедии для получения общей информации о многомерных массивах в C.

Ваш код должен работать с этим:

int* big[] = {ar1, ar2, ar3, ar4};
1 голос
/ 17 сентября 2011

AC 2-мерный массив - это не что иное, как массив массивов.Такой двумерный массив не может быть «рваным», т. Е. Каждая строка должна иметь одинаковое количество элементов.Для вашего конкретного случая вы можете объявить его следующим образом:

int big[4][4] =
    { { 1, 2, 3, 4 },
      { 10, 12, 13, 14 },
      { 8, 9, 15, 16 },
      { 17, 18, 19, 20 } };

Вы можете опустить первое измерение: int big[][4] = ..., и длина будет определена инициализатором, но вы не можете пропустить второе.

Одним из преимуществ этого подхода является то, что это один объект, и вы можете использовать sizeof для определения количества элементов:

sizeof big == 16 * sizeof (int)
sizeof big[0] == sizeof *big == 4 * sizeof (int)
sizeof big[0][0] == sizeof (int)

Но недостатком является то, что размерыисправлено.

Другой подход заключается в использовании массива указателей, где каждый указатель указывает на первый элемент массива:

int row0[] = { 1, 2, 3, 4 };
int row1[] = { 10, 12, 13, 14 };
int row2[] = { 8, 9, 15, 16 };
int row3[] = { 17, 18, 19, 20 };

int *big[4] = { row0, row1, row2, row3 };

(В инициализаторе row0 - это массивимя, но он распадается на указатель на первый элемент, также для row1, row2 и row3).Это более гибко, но вы должны отслеживать количество элементов в каждой строке;sizeof big[0] даст вам размер указателя, а не самой строки.

Еще один подход - сделать big указатель на указатель:

int row0[] = { 1, 2, 3, 4 };
int row1[] = { 10, 12, 13, 14 };
int row2[] = { 8, 9, 15, 16 };
int row3[] = { 17, 18, 19, 20 };

int *rows[] = { row0, row1, row2, row3 };

int **big = rows;

Этоеще более гибким (и на практике вы, вероятно, выделите все с помощью malloc().

. Четвертый подход, возможно, не очень полезный, состоит в том, чтобы сделать big массивом указателей на массивы; я выиграл 'не вдаваться в подробности этого.

Из-за правил затухания массива в указатель, хотя big имеет 4 разных типа в 4 разных случаях, вы можете использовать один и тот же синтаксис для ссылки наint элементов: big[x][y].

Рекомендуемое прочтение, как всегда: раздел 6 comp.lang.c FAQ .

0 голосов
/ 17 сентября 2011

, так как вы знаете элементы в каждом массиве (т.е. 4), вы можете легко создать больший массив, имеющий 16 элементов .... arr1, arr2, arr3, arr4 и arr5 (все 4 массива будут сохранены в нем) Вы можете пройти по большому массиву и заполнить содержимое для меньших массивов

arr5 -> [4 элемента] arr1 ---------- [4 элемента] arr2 -------- [4 элемента] arr3 ------- [4 элемента ] arr4 ========== [16 элементов]

for (i = 0; i <16; i ++) // обход большего массива) {</p>

// для первого массива, заполните содержимое и увеличьте i, это заполнит больший массив для (J = 0; J <4; j ++, я ++) arr5 [I] = arr1 [J]; аналогично для других массивов </p>

}

0 голосов
/ 17 сентября 2011

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

Итак, допустим, мы создаем единое целоемассив, вектор:

int vec[] = {0, 1, 2, 3 };

В памяти это место с именем vec

vec:
     DS  0
     DS  1
     DS  2
     DS  3

, где DS просто говорит «определить хранилище и инициализировать»с ".

Когда вы пишете цикл for для его итерации:

int ix;
for(ix=0; ix < 4; ix++){
   printf("%d\n", vec[ix]);
}

он становится циклом, похожим на

ix:    DS 0
loop:  CMP ix, 4
       JGE end     ; jump if comparison is >=
       PUSH vec+ix ; address arithmetic
       JSR PRINTF  ; call the printf routing using value on the stack
       INC ix      ; ix := ix+1
       JUMP loop   ; goto top
end:  

(Это неконкретный ассемблер, просто псевдокод.)

Теперь давайте создадим 2d массив

int ary2[][] = {{0,1,2,3},{4,5,6,7});
int ix, jx;
for(ix=0; ix<4;ix++){
   for(jx=0; jx<4; jx++){
      printf("%d\n", ary2[ix][jx]);
   }
}

В памяти, который просто становится

ary2:
     DS 0
     DS 1
     DS 2
     DS 3
     DS 4
     DS 5
     DS 6
     DS 7

другими словами, простоеще одна капля памяти.Наш цикл становится

ix:   DS  0
jx:   DS  0
;; Now, the compiler helps us a little bit: it "remembers" that
;; the inner array is 4 long.  We'll keep that around as 'len'
len:  DS  4
ofst: DS  0   ; and we'll keep a convenient variable for the "offset"
;; here's out loop
loop1:
      CMP ix, 4
      JGE end1
loop2:
      CMP  jx, 4
      JGE  end2
;; I'm going to cheat here.  ASSUME I've got a little
;; routine that multiplies ix*len and puts it in offset
      MLTOFFSET  ix,len
      ADD  jx, ofst
;; so what this all did was make ofst == (ix*len)+jx
      PUSH ary2+ofst
      INC  jx
      JUMP loop2
end2:
      INC ix
      JUMP loop1
end1:

Если вы пройдете через это, вы обнаружите, что ary2[ix][jx] превращается в ary2+0, ary2+1, ary2+2, ... ary2+6, ary2+7- и это именно те значения, которые вам нужны для того, чтобы один фрагмент памяти действовал как двумерный массив.

Один и тот же трюк, конечно, может выполняться для многихразмеры, как вы хотите;компилятор просто должен «запомнить», насколько большими будут шаги.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...