Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Битовый массив
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Кроcсплатформенный компилятор IAR
Muadib
как объявить битовый массив к примеру а[i][j] of byte и как с ним работать, помогите.
ViKo
Использовать битовые поля в структуре
Muadib
да но потом как обращатся к нему в цикле
struct {
unsigned j1: 1;
............
unsigned j90: 1;

} status[60];




Muadib
для ясности вот к примеру этот код, а как он будет выглядеть на си.

A:array[0..N,0..M]of byte; // и в места byte чтоб бит был, так как это в 8 раз меньше места занимает

for i := 1 to N do begin
for j := 1 to M do begin
T[i,j]=1;
end;
end;
_Артём_
Цитата(Muadib @ Apr 7 2012, 17:55) *
для ясности вот к примеру этот код, а как он будет выглядеть на си.

A:array[0..N,0..M]of byte; // и в места byte чтоб бит был, так как это в 8 раз меньше места занимает

for i := 1 to N do begin
for j := 1 to M do begin
T[i,j]=1;
end;
end;


На Си никак - типа bit не существует.
Можно пробовать на С++ что-нибудь: создать свой класс, перегрузить операторы и тд.
demitar
в с++ для этих целей есть std::vector<bool>, но, поскольку, он тяжелый, можно как-то так извратиться:

CODE
#include <iostream>
#include <cassert>

template <int SZ, typename BASE_T = unsigned int> // SZ - размер битового вектора,
class bitvec { // BASE_Т - базовый тип, в зависимости от архитектуры МК
BASE_T data[SZ / sizeof(BASE_T) + 1];
int shift;
int idx;

public:
bitvec<SZ>& operator[](int i) {
// при вызове оператора [] просто считаем индекс элемента в массиве и сдвиг
assert(i >= 0);
assert(i < SZ);
idx = i / sizeof(BASE_T);
shift = i & (sizeof(BASE_T) - 1);
return *this;
// возвращаем ссылку на себя, чтобы работало присваивание и преобразование типов
}

int operator=(int val) {
// записываем значение бита, индекс и сдвиг расчитали раньше с помощью []
val = val != 0;
data[idx] &= ~(1 << shift);
data[idx] |= (val << shift);
return val;
}

operator int() {
// приведение типа bitvec<> к int, чтобы работало присваивание a[i] = x, можно приводить к bool
return (data[idx] & (1 << shift)) >> shift;
}
};

// bitvec<15> test; // объявляем вектор из 15 бит

int main()
{
bitvec<10> bits[20]; // объявляем массив 20x10

for(int i = 0; i < 20; ++i) {
for(int j = 0; j < 10; ++j) {
bits[i][j] = (i * j) & 1; // пишем
std::cout << "bits[" << i << ", " << j << "] = ";
std::cout << bits[i][j] << " (" << ((i * j) & 1) << ") "; // читаем, что записали
std::cout << std::endl;
}
}

return 0;
}
scifi
Можно сделать функции для записи и чтения бита. Вот пример для одномерного массива:
CODE
#define NUMBITS 123

uint8_t bits[(NUMBITS + 7) / 8];

int getbit(uint8_t *src, int n)
{
return !!(src[n / 8] & (1 << (n % 8)));
}

void putbit(uint8_t *dst, int n, int val)
{
dst += n / 8;
if (val == 0)
{
*dst &= ~(1 << (n % 8));
}
else
{
*dst |= (1 << (n % 8));
}
}

int main(void)
{
putbit(bits, 34, 1);
printf("%d", getbit(bits, 34));
}
Muadib
вот мне вариант scifi: больше нравится поскольку памяти меньше занимает и по скорости шустрее будет чем вариант demitar
или я не прав? а для представления двумерного масива можно и одномерным обойтись.
_Артём_
Цитата(Muadib @ Apr 8 2012, 16:40) *
вот мне вариант scifi: больше нравится поскольку памяти меньше занимает и по скорости шустрее будет чем вариант demitar

А может больше нравится потому что понятней что написано?
Зато у demitar-а универсальней.
Насчёт скорости - вопрос. Как бы не одинаковая скорость, при прочих равных.

Цитата(Muadib @ Apr 8 2012, 16:40) *
памяти меньше занимает

И насколько меньше? Цифры есть?
demitar
Цитата(Muadib @ Apr 8 2012, 17:40) *
вот мне вариант scifi больше нравится поскольку памяти меньше занимает и по скорости шустрее будет чем вариант demitar
или я не прав? а для представления двумерного масива можно и одномерным обойтись.

да, будет чуть быстрее и меньше - за счет отсутствия сохранения промежуточных результатов в памяти. Точный ответ по скорости может дать только компилятор.
Как всегда, только Вам решать, что для Вас важнее - наглядность или экономия нескольких тактов/байт.
Muadib
Да конечно вариант scifi легче для понимания, цифр нет, но пробую оба варианта прокрутить а там видно будет.
scifi
Мой вариант хорош тем, что не требуется знания Си++. Кто бы что ни говорил, но язык Си значительно проще, и это его огромный плюс.
Pasha 111
Делал в своё время класс для работы с монохромным изображением. Тут, как я понял, нужно тоже самое.

Bitmap_mono.h
CODE
#ifndef _CCBITMAP_MONO_H
#define _CCBITMAP_MONO_H

// Типы данных
#ifndef TYPES_DEFINED
#define TYPES_DEFINED
typedef signed long long int64;
typedef signed int int32;
typedef signed short int int16;
typedef signed char int8;
typedef unsigned long long uint64;
typedef unsigned int uint32;
typedef unsigned short int uint16;
typedef unsigned char uint8;
#endif

class CBITMAP_MONO
{
private:
uint8 *buf;
uint32 width;
uint32 height;

public:
CBITMAP_MONO(void);
~CBITMAP_MONO(void);

uint32 bind(uint8 *new_buf, uint32 new_width, uint32 new_height);

void clear(uint32 color);
void invert();

void set_pixel(uint32 x, uint32 y, uint32 color);
uint32 get_pixel(uint32 x, uint32 y);
};
#endif


Bitmap_mono.cpp
CODE
//------------------------------------------------------------------------------

#include "Bitmap_mono.h"

//------------------------------------------------------------------------------

CBITMAP_MONO::CBITMAP_MONO(void)
{
buf = 0;
}

//------------------------------------------------------------------------------

CBITMAP_MONO::~CBITMAP_MONO(void)
{
}

//------------------------------------------------------------------------------

uint32 CBITMAP_MONO::bind(uint8 *new_buf, uint32 new_width, uint32 new_height)
{
if(new_buf == 0) return 0;
if(new_width == 0) return 0;
if(new_height == 0) return 0;

buf = new_buf;
width = new_width;
height = new_height;

return 1;
}

//------------------------------------------------------------------------------

void CBITMAP_MONO::clear(uint32 color)
{
uint32 size = width * height / 8;
if((width * height) % 8) size++;
if(color)
{
for(uint32 i = 0; i < size; i++) buf[i] = 0xFF;
}
else
{
for(uint32 i = 0; i < size; i++) buf[i] = 0x00;
}
}

//------------------------------------------------------------------------------

void CBITMAP_MONO::invert()
{
uint32 size = width * height / 8;
if((width * height) % 8) size++;
for(uint32 i = 0; i < size; i++) buf[i] = ~buf[i];
}

//------------------------------------------------------------------------------

void CBITMAP_MONO::set_pixel(uint32 x, uint32 y, uint32 color)
{
if(x >= width) return;
if(y >= height) return;

uint32 pix_num = y * width + x;
uint32 byte_num = pix_num / 8;
uint8 img_byte = buf[byte_num];

if(color)
{
img_byte |= 1 << (pix_num % 8);
buf[byte_num] = img_byte;
}
else
{
img_byte &= ~(1 << (pix_num % 8));
buf[byte_num] = img_byte;
}
}

//------------------------------------------------------------------------------

uint32 CBITMAP_MONO::get_pixel(uint32 x, uint32 y)
{
if(x >= width) return 0x000000;
if(y >= height) return 0x000000;

uint32 pix_num = y * width + x;
uint32 byte_num = pix_num / 8;
uint8 img_byte = buf[byte_num];

if(img_byte & (1 << (pix_num % 8))) return 0xFFFFFF;
else return 0x000000;
}

//------------------------------------------------------------------------------


Использование:

Код
const uint32 width = 20;
const uint32 height = 35;
uint8 buf[width * height / 8 + 1];

CBITMAP_MONO bmp;
bmp.bind(buf, width, height);

bmp.set_pixel(3, 14, 1);

if(bmp.get_pixel(3, 14))
{
    // ....
}


Да, если хочется юзать STL, то там есть стандартный контейнер - bitset
http://www.cplusplus.com/reference/stl/bitset/
Правда неизвестно как он реализован в IAR'е и сколько памяти будет занимать.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2014 Invision Power Services, Inc.