Форум программистов, компьютерный форум, киберфорум
Visual C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.53/456: Рейтинг темы: голосов - 456, средняя оценка - 4.53
Айхрень...
 Аватар для Paulie
306 / 176 / 7
Регистрация: 02.06.2009
Сообщений: 1,077

Использование #pragma pack(push,1)... pack(pop)

27.11.2009, 11:58. Показов 90455. Ответов 51
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день, товарищи.

Задался вопросом о записи в файл структур данных, читал читал в интернете много интересного. Наткнулся на статью, где описан такой вот вариант задания структур:

C++
1
2
3
#pragma pack (push, 1)
deftype struct {...}
#pragma pack ( pop)
Но почему-то автор не рекомендует использовать, вот я не совсем понял этот момент. Он описал как-то расплывчато пример, когда это не сработает...

Я использую структуру с уже определёнными размерами параметров, так что её размер не будет меняться во времени, проверил, у меня всё работает.

Но почему же автор всё-таки не рекомендует это использовать???
Может есть ещё интересные варианты?

Для записи в файл использую CreateFile, WriteFile (MSDN->System services->File services->file systems->file management)...

Заранее благодарю.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.11.2009, 11:58
Ответы с готовыми решениями:

[variadic pack][cdecl]
доброе утро. рассмотрим код: http://rextester.com/ATJJT68666 #include <iostream>

IAR EWARM, непонятное поведение data pragma pack
EWARM 6.50.6, понадобилось упаковать класс, чтобы красиво и грамотно гонять его туда-сюда по коммуникациям. По примеру сделал так: ...

Русские символы NT 4.0+Service pack 6 + Option pack + MS SQL7.0 с СР1251
Помогите пожалуйста!!!!!! имею NT 4.0+Service pack 6 + Option pack + MS SQL7.0 с СР1251 Выполняю код с подключением к базе через ODBC...

51
 Аватар для programina
2062 / 619 / 41
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
29.05.2012, 17:20
Студворк — интернет-сервис помощи студентам
Заменила все long'и на int'ы и теперь работает в 64-битном Минте, мб такое прокатит и в 32-битной системе
Вот небольшая программа превращающая превращает обычный рисунок в негатив
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <stdio.h>
 
#pragma pack(push,1)
struct BITMAPFILEHEADER {
    unsigned short  bfType;
    unsigned int    bfSize;
    unsigned short  bfReserved1;
    unsigned short  bfReserved2;
    unsigned int    bfOffBits;
};
#pragma pack(pop)
 
 
#pragma pack(push,1)
struct BITMAPINFOHEADER {
    unsigned int    biSize;
    unsigned int    biWidth;
    unsigned int    biHeight;
    unsigned short  biPlanes;
    unsigned short  biBitCount;
    unsigned int    biCompression;
    unsigned int    biSizeImage;
    unsigned int    biXPelsPerMeter;
    unsigned int    biYPelsPerMeter;
    unsigned int    biClrUsed;
    unsigned int    biClrImportant;
};
#pragma pack(pop)
 
 
#pragma pack(push,1)
struct PIXEL {
    unsigned char    b;
    unsigned char    g;
    unsigned char    r;
};
#pragma pack(pop)
 
 
 
int main()
{
    BITMAPFILEHEADER    fileheader;
    BITMAPINFOHEADER    infoheader;
    PIXEL               pixel;
    FILE                *fin, *fou;
 
    fin = fopen("picture1.bmp","rb+");
    fou = fopen("picture2.bmp","wb+");
 
    fread( &fileheader, sizeof(BITMAPFILEHEADER), 1, fin );
    fread( &infoheader, sizeof(BITMAPINFOHEADER), 1, fin );
 
    fwrite( &fileheader, sizeof(BITMAPFILEHEADER), 1, fou );
    fwrite( &infoheader, sizeof(BITMAPINFOHEADER), 1, fou );
 
    for (int i = 0; i < infoheader.biWidth*infoheader.biHeight; i+=1)
    {
        fread( &pixel, sizeof(PIXEL), 1, fin );
        pixel.b = 255 - pixel.b;
        pixel.g = 255 - pixel.g;
        pixel.r = 255 - pixel.r;
        fwrite( &pixel, sizeof(PIXEL), 1, fou );
    }
    fclose(fin);
    fclose(fou);
    return 0;
}
Миниатюры
Использование #pragma pack(push,1)... pack(pop)   Использование #pragma pack(push,1)... pack(pop)  
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
29.05.2012, 17:36
Цитата Сообщение от programina Посмотреть сообщение
мб такое прокатит и в 32-битной системе
Прокатит. Но не прокатит на big endian машинах типа sparc'а (где порядок байтов в слове обратный)

И более аккуратно было бы делать что-то типа:

C
1
2
3
4
5
6
7
8
9
10
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
 
struct BITMAPFILEHEADER {
    uint16_t bfType;
    uint32_t bfSize;
    uint16_t bfReserved1;
    uint16_t bfReserved2;
    uint32_t bfOffBits;
};
Ну и так далее. С тем, чтобы если что-то надо поменять, то меняются только две строчки, а не миллион
1
 Аватар для programina
2062 / 619 / 41
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
29.05.2012, 18:01
Цитата Сообщение от Evg Посмотреть сообщение
C
1
2
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
Работает. Теперь буду делать только так.
0
Делаю внезапно и красиво
Эксперт С++
 Аватар для Deviaphan
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 10:57
Цитата Сообщение от programina Посмотреть сообщение
превращает обычный рисунок в негатив
У тебя не правильные структуры: Высота может быть отрицательной.
Ну и в начале нужна проверка, что это 24 битная картинка.
0
1 / 1 / 0
Регистрация: 19.07.2013
Сообщений: 21
26.07.2013, 00:01
Добавлю 3 комейки.
Еще не докопавшись до #pragma pack, решил, что (поскольку типы данных - ряд факториала) просто надо составлять структуры, помещая вверх самые объемные типы... и вниз по убывающей. А в конце ставить "пустой" член структуры, дополняющий размер структуры до размера, кратного размеру наибольшего типа.
В редких случаях, когда структура состит всего из двух членов, один из которых имеет тип максимального размера, а другой - минимального, "потери" памяти будут ощутимы.(реальных программ, в которых это может сказаться - еще меньше)
В большинстве же случаев они будут ничтожны. Зато хорошая скорость и гарантия не столкнуться с одной проблемой.

А вот застраховаться от различия в размере типов данных в разных... ситуациях - получается нельзя? - Это жаль. Разве что завести себе за правило всегда проверять типы при переходе на новое место?

Добавлено через 23 минуты
Только не "ряд факториала", а геом.прогрессия

Добавлено через 10 минут
А лучше всего было бы выбирать размер типов данных самому... из некоторого набора.
А может это возможно?
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
02.12.2015, 13:34
Используя пример Evg
C++
#pragma pack (push, X)
struct
{
  char f1;
  int f2;
  short f3;
};
#pragma pack (pop)
нарисовал свою любимую священную всеобъясняющую картинку:



Использовать push с цифрой восемь и более, в данном примере, не имеет смысла потому, что размер наибольшего элемента структуры - int (четыре байта) меньше, чем эти параметры. И автоматом будет приводиться по наибольшему элементу структуры.
1
0 / 0 / 0
Регистрация: 23.12.2016
Сообщений: 4
23.12.2016, 11:51
Спасибо Evg за пример с #pragma pack. Долго искал эту ценную информацию.
Моя задача в том, чтобы данные разной длины из структуры отправить байт за байтом. Для этого я хочу использовать одну и ту же часть памяти и как структуру с данными разной длины и как массив с ячейками по 8 бит.
То есть мне это нужно для того, чтобы из структуры с данными разной длины быстро получить массив данных по 8 бит.
Для этого важно, чтобы данные в структуре расположились в памяти без пробелов.
я создам 8-ми битный массив и наложу на него структуру. Благодаря #pragma pack (push, 1) данные структуры будут расположены в памяти без пробелов.

Вопрос: А байтовый массив может оказаться расположен в памяти с пробелами? Как я понял на эксперименте - нет. Да и по логике.

Вот пример как наложить структуру на массив (обращаться к массиву как к структуре):
C
1
2
3
4
5
6
7
8
9
10
/* [url]http://learnc.info/c/structures.html[/url]
Привести массив к структуре (или любому другому типу) по стандарту также
невозможно (хотя в различных компиляторах есть для этого инструменты).
Но в си возможно всё.
Но запомните, что в данном случае поведение не определено. -???
*/
    struct Point_t point1 = {10, 20};
    int x[3] = {300, 400, 500};
    point1 = (*(struct Point_t*)(x)); // волшебная строка
    printf("a = %d, b = %d", point1.x, point1.y);//структура выводит содержание массива
Кто знает - что означает звёздочка после типа: struct Point_t* ?

А как наоборот - наложить массив на структуру (обращаться к структуре как к массиву)?

Добавлено через 43 минуты
А как наоборот - наложить массив на структуру (обращаться к структуре как к массиву)? Нашёл ответ сам:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/* ************************** */
/* как наложить массив на структуру, точнее взять данные структуры как из 8-ми битного массива: */
 
// пример взят отсюда: [url]http://dml.compkaluga.ru/forum/index.php?showtopic=102963[/url]
// пример с #pragma pack (push, 1) взят отсюда: [url]https://www.cyberforum.ru/visual-cpp/thread67902.html[/url]
/* Создать тип структуры, данные которой располагаются в памяти без пробелов */
#pragma pack (push, 1)
struct xx {
uint8_t a;
uint8_t b;
uint32_t c;
};
#pragma pack (pop)
 
/* Объявим указатель на нашу структуру */
struct xx *xx_ptr;
 
/* и выделим под нее участок памяти */
xx_ptr = malloc(sizeof(struct xx));
 
/* Запишем что нибудь в нашу структуру */
xx_ptr->a = 0xAA;
xx_ptr->b = 0xBB;
xx_ptr->c = 0x12345678;
 
/* Заведем еще один - байтовый указатель, возьмем адрес нашей структуры
и пройдемся по ней, распечатывая каждый байт */
uint8_t *byte_ptr; //создать байтовый указатель
byte_ptr = (uint8_t *) xx_ptr; //поместить в указатель адрес структуры
int i=0;
while(i < sizeof(struct xx)) {
printf("[%04d] %02X\n", i, *(byte_ptr+i)); //вывод структуры побайтно
++i;
}
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
23.12.2016, 13:26
Цитата Сообщение от dvkobzev Посмотреть сообщение
Вопрос: А байтовый массив может оказаться расположен в памяти с пробелами? Как я понял на эксперименте - нет. Да и по логике
Не может (если я вопрос понял правильно)

Цитата Сообщение от dvkobzev Посмотреть сообщение
Кто знает - что означает звёздочка после типа: struct Point_t* ?
Звёздочка означает указатель. С такими вопросами обычно отправляют читать учебники
0
0 / 0 / 0
Регистрация: 23.12.2016
Сообщений: 4
23.12.2016, 14:42
В учебниках я не нашёл почему звёздочка то до названия, то после названия:
point1 = (*(struct Point_t*)(x));
Как расшифровывается эта строка? point1 - это указатель типа "struct Point_t" , а дальше..?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
23.12.2016, 15:05
преобразовать "x" к типу "struct Point_t*", а потом разыменовать (самая первая звёздочка)
0
0 / 0 / 0
Регистрация: 23.12.2016
Сообщений: 4
23.12.2016, 17:05
Цитата Сообщение от Evg Посмотреть сообщение
к типу "struct Point_t*"
тип struct Point_t - это понятно:
C
1
2
3
4
struct Point_t {
    int x;
    int y;
};
Так было бы понятно:
struct Point_t *xx_ptr; //xx_ptr-указатель на структуру

Но что такое тип struct Point_t* ?

Добавлено через 18 минут
Понял: тип struct Point_t* - это "Указатель типа struct Point_t"

Вот простой пример:

void *p; // Указатель обобщенного типа
int *a; // Указатель на целое число
a = (int*) p; // Указатель а пусть станет равным указателю р после его приведения к типу "Указатель на целое число"

Взято от сюда: http://www.intuit.ru/studies/c... 974?page=7
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
23.12.2016, 21:03
У тебя уже набралось 3 поста, по идее ты уже можешь темы создавать. Создай себе по одной теме на каждый интересующий тебя вопрос. В теме про упаковку структур ты всё равно не найдёшь желающих обучать тебя базовым основам из учебника
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.12.2016, 21:03
Помогаю со студенческими работами здесь

Pack() [function.pack]: Type H: illegal hex digit m in
Возникла довольно странная проблема, при загрузке страницы вылезает Warning: pack() : Type H: illegal hex digit m in, в чем может быть...

Сделать так чтобы если вводится push выполнялась функция push, если pop то pop
Помогите пожалуйста с данным вопросом: например у меня есть список и несколько возможных с ним операций (например push - добавить элемент...

Push, Pop
Вот такое задание: F=Ʃ от 1 до 5 f (Ai) A1=2 Ai+1=Ai+2 Ai=(3*A)+(C/D). Нужно записать эту формулу в ассемблере с помощью Push, Pop...

push и pop
У меня возникла странная проблема. Мы создали сайт на основе системы управления, которой пользовались не один раз. Все сайты нормально...

Функции pop и push
Здравствуйте, есть код, решающий задачу. В нем есть стандартные функции push и pop. Как можно расписать функции подробно pop и push?...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
52
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru