Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Прокомментируйте код


Автор: anwe 9.7.2008, 19:16
Опишите (прокомментируйте), пожалуйста, эти строки:
Код

BYTE bpp;
DWORD TransPixel;
...
bpp = bi.bmBitsPixel >> 3;
BYTE *pBits = new BYTE[ bi.bmWidth * bi.bmHeight * bpp ];
int  p = GetBitmapBits( maskBitmap, bi.bmWidth * bi.bmHeight * bpp, pBits );
TransPixel = *(DWORD*)pBits;
TransPixel <<= 32 - bi.bmBitsPixel;

4-я строка - это, что, сдвиг вправо на 3 разряда? В 5-ой строке понимаю идет выделение памяти, но ее размер байт что ли? Из условия задачи знаю, что bi.bmWidth и bi.bmHeight =200, то есть уже больше байта.
Описание переменных, ясное дело, понятно. Меня интересует сам код.

Автор: creatorcode 9.7.2008, 19:35
Цитата(anwe @  9.7.2008,  19:16 Найти цитируемый пост)
В 5-ой строке понимаю идет выделение памяти, но ее размер байт что ли

выделяется память под массив байт размером  bi.bmWidth * bi.bmHeight * bpp
bpp по всей видимости - это кол-во байт на пиксел.

Автор: anwe 9.7.2008, 20:04
Уже лучше, а остальное?

Нет не лучше: bi.bmWidth * bi.bmHeight * bpp однозначно больше байта, ведь 
Цитата

bi.bmWidth и bi.bmHeight =200, то есть уже больше байта

Автор: system 9.7.2008, 20:22
Цитата(anwe @  9.7.2008,  20:04 Найти цитируемый пост)
однозначно больше байта, ведь 

это не конструктор а массив,
 какая разница что количество элементов больше 1 байта

Автор: anwe 9.7.2008, 20:26
Так, это понятно, просто в фразе
Цитата(creatorcode @  9.7.2008,  18:35 Найти цитируемый пост)
выделяется память под массив байт размером  bi.bmWidth * bi.bmHeight * bpp

меня смутило что bi.bmWidth * bi.bmHeight * bpp - это элементы массива. А это его размер.
Все, ясно. Что с остальными строками? Опишите!!!

Автор: system 9.7.2008, 21:11
Код

BYTE bpp; //Объявление переменной типа BYTE
DWORD TransPixel; // Объявление переменной типа DWORD
...
bpp = bi.bmBitsPixel >> 3; // приравнивание переменной bpp значения
//  bi.bmBitsPixel со сдвигом вправо на 3 позиции пример 
// было 11000000  стало 00011000

BYTE *pBits = new BYTE[ bi.bmWidth * bi.bmHeight * bpp ]; //объявление указателя *pBits на массив из
// BYTE из bi.bmWidth * bi.bmHeight * bpp  элементов

int  p = GetBitmapBits( maskBitmap, bi.bmWidth * bi.bmHeight * bpp, pBits ); //объявляется переменна p которой приравнивается значение вызываемой функции GetBitmapBits 
TransPixel = *(DWORD*)pBits; // переменной TransPixel приравнивается значение pBits,  с преобразованием к типу в си стиле
TransPixel <<= 32 - bi.bmBitsPixel; // приравнивание TransPixel  самой себя со сдвигом влево на 3 позиции
//пример противоположный примеру выше

Автор: anwe 9.7.2008, 21:34
По последним двум строкам кода уточнения:
Код

TransPixel = *(DWORD*)pBits;

Теперь переменная TransPixel также содержит указатель на вновь объявленный массив?

Код

TransPixel <<= 32 - bi.bmBitsPixel;

Наверное, приравнивание не самой себя а так: значение TransPixel отнимается от 32, сдвигается влево на 3 разряда и снова заносится в TransPixel. Верно?

Автор: bsa 9.7.2008, 22:29
anwe
Код
TransPixel = *(DWORD*)pBits;
Это преобразование указателя pBits к указателю на двойное слово, а затем присвоение этого двойного слова переменной TransPixel 
Код
TransPixel <<= 32 - bi.bmBitsPixel;
Это сдвиг значения TransPixel на разность 32 и bi.bmBitsPixel битов влево. Обычно, bmBitsPixel равен, 1, 4, 8, 15, 16, 24 и 32. Соответственно сдвиг будет на 31, 28, 17, 16, 8 и 0 разрядов.

Автор: mes 9.7.2008, 23:59
Цитата(anwe @  9.7.2008,  19:16 Найти цитируемый пост)
bpp = bi.bmBitsPixel >> 3;

">> 3 " в данном случае выполняет роль целочисленного деления ( /8 ), результат которого будет минимальное кол-во байтов нужное для хранения одного пикселя. 

Автор: system 10.7.2008, 01:51
Цитата(anwe @  9.7.2008,  21:34 Найти цитируемый пост)
Наверное, приравнивание не самой себя а так: значение TransPixel отнимается от 32, сдвигается влево на 3 разряда и снова заносится в TransPixel. Верно? 

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

TransPixel <<= 32 - bi.bmBitsPixel;

равнозначен : 
Код

 int x = 32 - bi.bmBitsPixel;
TransPixel <<=  x;

или еще проще
Код

 int x = 32 - bi.bmBitsPixel;
TransPixel = TransPixel << x; // сдвиг на x влево

Автор: anwe 10.7.2008, 21:45
Спасибо всем, но есть но.
Снова здорово:
Код

BYTE *pBits = new BYTE[ bi.bmWidth * bi.bmHeight * bpp ];

выделяет массив байт и этот массив имеет размерность bi.bmWidth * bi.bmHeight * bpp. Раз выделяет память, значит результат ее - указатель.
Вопрос: как он, указатель, может быть байтом? smile Или другими словами: как понимать BYTE *pBits?

Автор: varnie 10.7.2008, 22:12
выделяется память под  bi.bmWidth * bi.bmHeight * bpp  байт, и в переменную pBits закидывается указатель на этот блок выделенной памяти. а сама переменная pBits является просто указателем на байт. в д. случае она указывает на начало выделенного блока.

Автор: JackYF 10.7.2008, 22:44
Цитата(anwe @  10.7.2008,  20:45 Найти цитируемый пост)
как он, указатель, может быть байтом?

Указатель не байт, указатель указывает на байт smile

Автор: anwe 10.7.2008, 22:50
То есть, BYTE показывает, что она указывает на первый байт выделенной памяти? Так это и так ясно, что указатель указывает на первый байт чего-либо. Что, значит, к примеру, BYTE *pBits указывает на первое двойное слово выделенной памяти? Если да, то как то странно, значение адреса ведь, что у байта что у двойного слова одно и переменная pBits в любом случае будет содержать один и тот же адрес.

Автор: varnie 10.7.2008, 22:57
BYTE b; //переменная типа BYTE (т.е. unsigned char)
BYTE *pByte //переменная, указывающая на байт. в мире виндовс есть также определенный тайпдеф(typedef), PBYTE -- это то же самое что и "BYTE *".
pByte в данном случае указывает не на первое двойное слово памяти, а на первый байт аллоцированной памяти.

cкажем, есть у нас BYTE *pByte = new BYTE[10];
если мы сделаем: DWORD  pDword = (DWORD *)pByte; ++pDword;
то мы сдвинемса от начала выделенного блока состоящего из 10 байт на 4 байта. т.е. "шагать" по памяти будем "4байтными" шагамиsmile в нек. случаях это очень удобно.
если бы мы двигались имея изначальный pByte, то после ++pByte мы бы сдвинулись не на 4 байта, а лишь на один.

Автор: anwe 10.7.2008, 23:01
Вопрос исчерпан.
Спасибо.

Автор: varnie 10.7.2008, 23:08
я чуть-чуть отредактировал свое предыдущее сообщение. прочтиsmile

Автор: anwe 11.7.2008, 00:22
varnie, приблизительно такое пояснение я и ожидал и... если в этом и вся разница, то  это просто мне к сведению. А уж как перемещаться по памяти - СООРИЕНТИРУЕМСЯ  smile . Мне просто надо было разъяснить код.

Тема закрыта!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)