Напомните, какую часть проблемы не решает следующая проблема ...
DROP TABLE IF EXISTS product;
CREATE TABLE product
(id SERIAL PRIMARY KEY
,title VARCHAR(30) NOT NULL
,pages INT NOT NULL
);
INSERT INTO product VALUES
(1,'Harry Potter',230),
(2,'Lord of the Rings',950),
(3,'Game of Thrones',980);
DROP TABLE IF EXISTS prices;
CREATE TABLE prices
(product_id INT NOT NULL
,book_type INT NOT NULL
,price DECIMAL(5,2) NOT NULL
,PRIMARY KEY(product_id,book_type)
);
INSERT INTO prices VALUES
(1,0,20.40),
(1,1,28.00),
(1,2,40.00),
(2,0,15.00),
(2,1,25.50),
(2,2,42.00),
(3,0,21.00),
(3,1,30.50),
(3,2,47.00);
SELECT c.*
, a.*
FROM prices a
JOIN prices b
ON b.product_id = a.product_id
JOIN product c
ON c.id = b.product_id
WHERE b.price LIKE '%1%';
+----+-------------------+-------+------------+-----------+-------+
| id | title | pages | product_id | book_type | price |
+----+-------------------+-------+------------+-----------+-------+
| 2 | Lord of the Rings | 950 | 2 | 0 | 15.00 |
| 2 | Lord of the Rings | 950 | 2 | 1 | 25.50 |
| 2 | Lord of the Rings | 950 | 2 | 2 | 42.00 |
| 3 | Game of Thrones | 980 | 3 | 0 | 21.00 |
| 3 | Game of Thrones | 980 | 3 | 1 | 30.50 |
| 3 | Game of Thrones | 980 | 3 | 2 | 47.00 |
+----+-------------------+-------+------------+-----------+-------+
Посмотрите этот вопрос: Почему sizeof для структуры не равен сумме sizeof каждого участника?.
Я полагаю, что компилятор понимает намек для отключения дополнения при использовании "неподписанного интервала wWindow:16" синтаксис.
Кроме того, обратите внимание, что короткими, как гарантируют, не составят 16 битов. Гарантия то, что: 16 битов <= размер короткого <= размер интервала.
Поскольку компилятор упаковывает Ваше битовое поле в 32-разрядный интервал, не 16-разрядный объект.
В целом необходимо избежать битовых полей и использовать другие явные константы (перечисления или безотносительно) с явным побитовым маскированием и смещающийся для доступа к 'подполям' в поле.
Вот одна причина, почему битовых полей нужно избежать - они не являются очень портативными между компиляторами даже для той же платформы. из стандарта C99 (существует подобная формулировка в стандарте C90):
Реализация может выделить любое адресуемое устройство хранения данных, достаточно большое для содержания битового поля. Если достаточно пространства останется, то битовое поле, которое сразу следует за другим битовым полем в структуре, должно быть упаковано в смежные биты той же единицы. Если недостаточное пространство остается, помещается ли битовое поле, которое не соответствует, в следующую единицу или накладывается, смежные единицы определяется реализацией. Порядок выделения битовых полей в единице (старший разряд к или младшему разряду младшего разряда к старшему разряду) определяется реализацией. Выравнивание адресуемого устройства хранения данных является неуказанным.
Вы не можете гарантировать, 'охватит' ли немного поля международную границу или не, и Вы не можете указать, запускается ли битовое поле в низкопроизводительном из интервала или верхнем уровне интервала (это независимо от того, с обратным порядком байтов ли процессор или с прямым порядком байтов).
Компилятор дополняет участника структуры небитового поля к 32-разрядному - собственное выравнивание слов. Для фиксации этого сделайте пакет #pragma (0) перед структурой и пакетом #pragma () после.
Интересный - я думал бы, что "WORD" оценит к "короткому целому без знака", таким образом, у Вас была бы та проблема больше чем в одном месте.
Также знайте, что необходимо будет заниматься проблемами порядка байтов в любом значении более чем 8 битов.
Ваши серии "неподписанного int:xx" битовые поля израсходовали только 16 из 32 битов в интервале. Другие 16 битов (2 байта) там, но неиспользованный. Это сопровождается коротким целым без знака, которое находится на международной границе и затем WORD, который является вдоль выровненного на международной границе, что означает что там 2 байта дополнения между ними.
Когда Вы переключаетесь на "неподписанный интервал wWindow:16", вместо того, чтобы быть отдельным коротким, компилятор использует неиспользованные части предыдущего битового поля, таким образом, никакие отходы, нет короткие, и никакое дополнение после короткого, следовательно, Вы сохраняете четыре байта.
Не эксперт C/C++ когда дело доходит до упаковки. Но я предполагаю, что существует правило в спецификации, которая говорит, что, когда небитовое поле следует за битовым полем, оно должно быть выровненное на границе слова независимо от того, помещается ли оно в остающееся пространство. Путем создания этого явным битовый вектором Вы избегаете этой проблемы.
Снова это - предположение с легким опытом.
Границы структуры в памяти могут быть дополнены компилятором в зависимости от размера и порядка полей.
Я думаю, что Mike B разобрался в нем, но но не совершенно ясный. Когда Вы просите "короткий", это выровненное на границе на 32 бита. Когда Вы просите int:16, это не. Таким образом, int:16 соответствует прямо после th поля прибыли до уплаты налогов и процентов, в то время как короткие пропуски 2 байта и запускается в следующем 32-разрядном блоке.
Остальная часть, что он говорит, совершенно применима - битовое поле никогда не должно использоваться для кодирования внешне видимой структуры, потому что нет никакой гарантии относительно того, как они выделяются. В лучшем случае они принадлежат встроенных программ, где сохранение байта важно. И даже там, Вы не можете использовать их для на самом деле controly биты в портах с отображенной памятью.
Вы видите различные значения из-за компилятора, упаковывающего правила. Вы видите правила, характерные для Visual Studio здесь.
Когда у Вас есть структура, которая должна быть упакована (или придерживаться некоторых определенных требований выравнивания), необходимо использовать пакет #pragma () опция. Для Вашего кода можно использовать пакет #pragma (0), который выровняет все элементы структуры на границах байта. Можно затем использовать пакет #pragma () для сброса упаковки структуры к, он - состояние по умолчанию. Вы видите больше информации о прагме пакета здесь.