Зубчатый массив в C (3D)

Как я мог сделать следующее?

double layer1[][3] = {
    {0.1,0.1,0.8},
    {0.1,0.1,0.8},
    {0.1,0.1,0.8},
    {0.1,0.1,0.8}
};
double layer2[][5] = {
    {0.1,0.1,0.1,0.1,0.8}
};
double *upper[] = {layer1, layer2};

Я прочитал следующее после попытки разных идей; но безрезультатно. Существуют ли зазубренные массивы в C/C++?

Я понимаю (надеюсь) что

double **upper[] = {layer1, layer2};

Это похоже на то, что я хотел бы, но не будет работать, потому что слои не являются массивами указателей. Я использую C намеренно.


Я пытаюсь воздержаться от этого (что работает).

double l10[] = {0.1,0.1,0.8};
//l11 etc
double *l1[] = {l10,l11,l12,l13};
double l20[] = {0.1,0.1,0.1,0.1,0.8};
double *l2[] = {l20};

double **both[] = {l1, l2};

3 ответа

Решение

В современном C есть инструментальная составляющая вызова литерала, чтобы хотя бы частично достичь того, чего вы хотите:

double (*(layer1[])) = {
  (double[]){0.1,0.1,0.8},
  (double[]){0.1,0.1,0.8},
  (double[]){0.1,0.1,0.8},
  (double[]){0.1,0.1,0.8}
};
double (*(layer2[])) = {
    (double[]){0.1,0.1,0.1,0.1,0.8}
};
double (*(*(upper[]))) = {layer1, layer2};

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

Изменить: конструкция как (double[]){ 0.0 } называется составным литералом и имеет тот же эффект, что и ваши временные массивы, которые вы объявили во второй версии. Преимущество заключается в том, что вам не нужно придумывать для них соглашение об именах, и что единственный способ получить доступ к этим временным переменным - это использовать массив большего размера. Может быть, было бы лучше положить в const во все это, чтобы вы не могли случайно изменить указатели:

double (*const(layer1[])) = {
  (double[]){0.1,0.1,0.8},
  (double[]){0.1,0.1,0.8},
  (double[]){0.1,0.1,0.8},
  (double[]){0.1,0.1,0.8}
};
double (*const(layer2[])) = {
    (double[]){0.1,0.1,0.1,0.1,0.8}
};
double (*const(*const(upper[]))) = {layer1, layer2};

Это все еще позволяет вам изменить содержимое (все doubles) но не указатели. Если вы знаете, что doubles сами не меняются в течение всей программы, меняются double в double const везде.

struct {
  size_t length;
  size_t stride;
  double *data;
} upper = {
  {
    sizeof(layer1) / sizeof(layer1[0]),
    sizeof(layer1[0]) / sizeof(layer1[0][0]),
    (double *)layer1,
  },
  {
    sizeof(layer2) / sizeof(layer2[0]),
    sizeof(layer2[0]) / sizeof(layer2[0][0]),
    (double *)layer2,
  },
};

int i, j, k;
for (i = 0; i < sizeof(upper) / sizeof(upper[0]); i++) {
  for (j = 0; j < upper[i].length; j++) {
    for (k = 0; i < upper[i].stride; k++)
      printf(" %d" + !k, upper[i].data[upper[i].stride * j + k]);
    printf("\n");
  }
  printf("\n");
}

Вы должны понимать, что многомерные массивы в C просто упакованы в линейную часть памяти. Фактические измерения известны только типам во время компиляции: их нет нигде в данных во время выполнения.

Layer1 и Layer2 - это массивы указателей, по определению зазубренные массивы. Там нет причин для

double ** upper[] = {layer1, layer2}

Не работать. Если это не так, опубликуйте сообщение об ошибке.

Единственная проблема заключается в том, что ваши массивы распадаются на указатели. Если это проблема для вас, вам нужно использовать C99 и прочитать этот пост в ветке, которую вы уже упоминали.

Другие вопросы по тегам