Как объявить массив указателей на многомерные массивы - PullRequest
0 голосов
/ 26 января 2012
// LED definitions for each step
static uint8_t route1Step0LedsOn[] = { 0x30, 0xff };
static uint8_t route1Step0LedsOff[] = { 0x26, 0xff };
static uint8_t route1Step1LedsOn[] = { 0x18, 0x45, 0x21, 0xff };
static uint8_t route1Step2LedsOn[] = { 0x56, 0x33, 0x42, 0x31, 0xff };

// First route (consisting of 3 steps + terminator).
static uint8_t* routeLeds1[][2] =
{
    { route1Step0LedsOff, route1Step0LedsOn },
    { NULL,               route1Step0LedsOn },
    { NULL,               route1Step0LedsOn },
    { NULL,               NULL }
};

// Second route.
static uint8_t* routeLeds2[][2] =
{
    // LED elements not shown, but similar to route 1.
    { NULL,               NULL }
};

// Array of routes.
static ??? routes[] =
{
    NULL,
    routeLeds1,
    routeLeds2,
    NULL
};

Я не уверен в правильности типа для routes[].

Я бы хотел знать, каким должен быть ???

Я использую микроконтроллер и ДОЛЖЕН использовать массивы для принудительного помещения массивов во флэш-память вместо ОЗУ.

Ответы [ 4 ]

3 голосов
/ 26 января 2012

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

В памяти «указатель на указатель ...» на объект представлен

a -> b -> c -> ... -> object

Где a, b, c, ... и object находятся в совершенно разных частях памяти. Чтобы проиндексировать указатель, указатель разыменовывается.

Однако массивы хранятся в непрерывной памяти. Например, int a[2][2] будет

[0,0][0,1][1,0][1,1]

Индексирование многомерного массива не разыменовывает указатель, оно меняет арифметику, которая используется для вычисления смещения от начала массива, в котором находится желаемое значение. Формула будет

адрес массива + index 1 * sizeof (первое измерение) + index 2 * sizeof (второе измерение) + ... + index n * sizeof (объект)

Где sizeof(nth dimension) - это размер всех вложенных измерений. Например, с int a[3][2], который представлен

[0,0][0,1][1,0][1,1][2,0][2,1]

, индекс a[2][1] будет

адрес a + 2 * (sizeof (int) * 2) + 1 * sizeof (int)

Который в C ++ будет (char*)a + 16 + 4, последним элементом массива.

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

<ч /> Мне трудно выразить все это словами; если я не имею смысла, скажите, пожалуйста.

1 голос
/ 26 января 2012

Попробуйте это:

typedef uint8* Array1; // first column/row
typedef Array1 Array2[2]; // uint* name[2]
typedef Array2* Array3; // get the idea?

// Array of routes.
static Array3 routes[] =
{
    NULL,
    routeLeds1,
    routeLeds2,
    NULL
};
0 голосов
/ 26 января 2012

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

struct LedList
{
   LedList( const std::vector<uint8_t> & v ) : leds( v ) {}
   std::vector<uint8_t> leds;
};

struct LedStep
{
  LedStep( const & LedList on_, const & LedList off_ ) : on_leds(on_), off_leds(off_) {}
  RouteStepLedList on_leds;
  RouteStepLedList off_leds;
};

struct LedRoute
{
  LedRoute( const std::vector<LedStep> & steps_ ) : steps(steps_) {}
  std::vector<LedStep> steps;
};

struct Route
{
  Route( const std::vector<LedRoute> & routes_ ) : routes(routes_) {}
  std::vector<LedRoute> routes;
};

//All routes
Route r( make_vector<LedRoute>()( 
    //First route
    make_vector<LedStep>()(
      //First step of first route 
      LedStep( 
        make_vector<uint8_t>()( 0x30 ),
        make_vector<uint8_t>()( 0x26 )
      ) )(
      //Second step of first route
      LedStep(
        make_vector<uint8_t>(),
        make_vector<uint8_t>()( 0x18 )( 0x45 )( 0x21 )
      ) )(
      //Third step of first route
      LedStep(
        make_vector<uint8_t>(),
        make_vector<uint8_t>()( 0x56 )( 0x33 )( 0x42 )( 0x31  )
     ) ) ),
     //Second route.
     make_vector<LedStep>()(
       //First step of second route
       LedStep( 
         ...
       ) ) (
       //Second step of second route
      ...
);
0 голосов
/ 26 января 2012

Ваша проблема - многомерный массив:

Если вам нужно пройти маршрут массива, вы можете просто добавить дополнительный шаг:

static uint8_t route1Step0LedsOn[] = { 0x30, 0xff };
static uint8_t* route1Step0[] = { NULL, route1Step0LedsOn };
static uint8_t** routeLeds1[] = { route1Step0 };
static uint8_t*** routes[] =
{
    NULL,
    routeLeds1,
    NULL
};

Если некоторые массивы имеют фиксированную длину, возможно, можно будет немного их очистить.

Но IMO это становится довольно уродливым и может быть связано с некоторыми реальными структурами, а не с массивами.

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