2015-07-14 4 views
0

Рассмотрим массив фреймбуферов определяется следующим образом:изменяя размерность выделенной памяти в с

static uint8_t framebuffer[num_buffers][1024];

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

framebuffer[buf][page][col];

Как это сделать? Используя реальные числа, я хотел бы, чтобы диапазон страниц был от 0 до 7, а col - от 0 до 127. Примечание: каждая страница составляет 128 байт. Например, это утверждение будет оценить, верно, потому что они будут ссылки на один и тот же байт:

framebuffer[0][130] == framebuffer[0][1][2]

потому 130/128 = 1 (стр) и 130% 128 = 2 (колонка). Я предполагаю, что мне нужно использовать malloc, но я не добился правильного поведения.

ответ

2

«Размерность» не является свойством выделенной памяти, а типом данных. Вы можете получить доступ к одной и той же памяти с помощью указателя другого типа с различными размерами, если вы позаботитесь о том, чтобы общий размер и выравнивание были совместимы. Так для примера, вы можете сделать:

static uint8_t framebuffer[numbuffers][1024]; 

uint8_t (*redimensioned)[8][128] = (uint8_t (*)[8][128])framebuffer; 

..и тогда, например, ноль 4-й столбец 3 страницы 2-го буфера с:

redimensioned[1][2][3] = 0; 

Выработать бит, оригинальная декларация uint8_t framebuffer[numbuffers][1024]; объявляет массив массивов (numbuffers массивов 1024uint8_t).Это будет распадаться на указатель на массивы 1024uint8_t-х (или uint8_t (*)[1024], которые также могут быть доступны как N x 1024 2-мерный массив.

Мы также можем получить доступ, что содержание исходного массива через указатель на массивы 8 массивов из 128uint8_t «с, что то, что uint8_t (*redimensioned)[8][128]; дает нам, и которые мы можем получить доступ как N x 8 x 128 3-мерного массива (после того, как указывает его на содержание исходного массива).

Чтобы компилятор счастливым, когда мы указываем redimensioned при заполнении framebuffer мы должны его бросить, так как типы p ointer framebuffer decays to отличается от типа указателя, который мы объявили ..., в котором происходит (uint8_t (*)[8][128]) в присваивании (это приведение к «указателю на массивы из 8 массивов из 128 uint8_t»).

+0

Все комментарии и ответы были полезны, но это именно то, что я представлял себе. Я думаю, что я знал это лучше, чем в настоящее время, потому что я довольно ржавый с C. «Конверсия», которую вы продемонстрировали, очень помогает. Благодарю. – Anthony

+1

Жюри по-прежнему не знает, действительно ли доступ к памяти через этот актерский закон, но он, вероятно, будет работать над реалиями реального мира –

1

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

uint8_t getFrameBufferItem(uint8_t framebuffer[][1024], 
          int i, 
          int j, 
          int k) 
{ 
    return framebuffer[i][j*128+k]; 
} 

Создайте аналогичную функцию для установки значения элемента.

void setFrameBufferItem(uint8_t framebuffer[][1024], 
         int i, 
         int j, 
         int k, 
         uint8_t val) 
{ 
    framebuffer[i][j*128+k] = val; 
} 
+0

Теперь я понимаю, что я не упоминал о том, что кадры должны быть написаны, а не просто читать. Это будет работать для чтения определенного байта, но мне также необходимо обновить их. – Anthony

+0

@ Энтони, см. Мой обновленный ответ. –

+0

@R Sahu благодарит за обновление. Я точно не помню, как это работает, но я предполагаю, что 'framebuffer [] [1024]' на самом деле является ссылкой. Разве накладные расходы на вызов функции не будут медленнее, чем первый ответ esm? – Anthony

1

У вас есть несколько вариантов. Во-первых, чтобы создать переменную, которая является двойной массив uint8_t указателей и сделайте следующее:

static uint8_t original_framebuffer[num_buffers][1024]; 
static uint8_t *new_framebuffer[num_buffers][8]; 
int i; 
for(i = 0; i < 8; i++) { 
    new_framebuffer[0][i] = &original_framebuffer[0][i * 128]; 
} 

Таким образом original_framebuffer[0][130] относится к той же ячейке памяти, как new_framebuffer[0][1][2]

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

#define XY_ACCESS(_x, _y) ((_x) * 128 + (_y)) 

Тогда вы бы следующее:

framebuffer[0][130] == framebuffer[0][XY_ACCESS(1, 2)] 

Конечно, вы можете использовать функцию вместо макроса.

+0

Умный. Макрос будет работать нормально, но первый метод будет быстрее, не так ли? Спасибо за вашу помощь. – Anthony

+1

@ Энтони, я бы угадал, что первый метод должен быть быстрее, поскольку умножения выполняются спереди, но первый метод использует больше обращений к памяти и, следовательно, может страдать больше промахов в кеше. Вам просто нужно было бы сравнить его – missimer

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