Форум программистов, компьютерный форум, киберфорум
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. Показов 89953. Ответов 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
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru