Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

Visual C++

Войти
Регистрация
Восстановить пароль
 
 
Paulie
Айхрень...
306 / 174 / 4
Регистрация: 02.06.2009
Сообщений: 1,078
#1

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

27.11.2009, 11:58. Просмотров 40846. Ответов 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
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.11.2009, 11:58
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Использование #pragma pack(push,1)... pack(pop) (Visual C++):

Распаковка parameter pack в наследуемых типах - C++
Есть класс наследуемый от переменного количества типов. Я не могу понять как можно сделать распаковку списка параметров с доступом к...

Обработка parameter pack через функции - C++
Суть - надо напечатать определенный аргумент (допустим третий) с пакета параметров функции. Чего то не соображу как. Вот код:#include...

#pragma - Visual C++
Научите пользоваться этой штуковиной. Интересует для начала что означает само слово pragma для VS и всё что можно сделать через неё.

Pragma comment() - Visual C++
Добрый день! Подскажите, пожалуйста, как быть, если компановщик игнорирует запись #pragma comment(exestr, L"My Programs"). VS 2010 Pro. Мне...

что такое #pragma once? - Visual C++
??????????

[c++, msvc] #pragma suppress warning - C++
Всем привет. Вижал студия 2013. Рассмотрим код: http://rextester.com/FCO39975 //Title of this code //Compiler Version...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
novi4ok
551 / 504 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
28.05.2012, 21:10 #31
я так понял, что если писатель написал УРА, то по ссылке - работающий код?
0
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
28.05.2012, 21:11 #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
#include <stdio.h>
 
#pragma pack(push,1)
struct BITMAPFILEHEADER_PRAGMA {
    unsigned short  bfType;
    unsigned long   bfSize;
    unsigned short  bfReserved1;
    unsigned short  bfReserved2;
    unsigned long   bfOffBits;
};
#pragma pack(pop)
 
struct BITMAPFILEHEADER_NOPRAGMA{
    unsigned short  bfType;
    unsigned long   bfSize;
    unsigned short  bfReserved1;
    unsigned short  bfReserved2;
    unsigned long   bfOffBits;
};
 
 
int main()
{
    BITMAPFILEHEADER_PRAGMA    pragma;
    BITMAPFILEHEADER_NOPRAGMA  nopragma;
    FILE                        *fin;
 
    printf("Действительный размер файла: 9270 байт\n");
 
    fin = fopen("picture1.bmp","rb+");
    fread( &pragma, sizeof(BITMAPFILEHEADER_PRAGMA), 1, fin );
    printf("bfSize c #pragma:\t%ld\n", pragma.bfSize);
    fclose(fin);
 
    fin = fopen("picture1.bmp","rb+");
    fread( &nopragma, sizeof(BITMAPFILEHEADER_NOPRAGMA), 1, fin );
    printf("bfSize без #pragma:\t%ld\n", nopragma.bfSize);
    fclose(fin);
 
    return 0;
}
0
Миниатюры
Использование #pragma pack(push,1)... pack(pop)  
Evg
Эксперт CАвтор FAQ
17808 / 6014 / 388
Регистрация: 30.03.2009
Сообщений: 16,525
Записей в блоге: 26
28.05.2012, 21:22 #33
Цитата Сообщение от novi4ok Посмотреть сообщение
я так понял, что если писатель написал УРА, то по ссылке - работающий код?
А что мешает взять да проверить?
1
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
28.05.2012, 22:02 #34
Цитата Сообщение от novi4ok Посмотреть сообщение
хотя в ссылке вроде УРА написано, так что автор нам просто причину может назвать в деталях.
в линуксе не используется WinAPI

PS: хотя может быть кто-то и использует
0
novi4ok
551 / 504 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
28.05.2012, 23:34 #35
мы, мне кажется, все трое "говорим параллельно". я не понимаю вообще, в чем проблема и что нужно проверять, при чем здесь winapi в линухе и пр. стою на шланге, короче, sorry ...

все люди действительно умерли, потому что ели огурци?
0
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
29.05.2012, 06:01 #36
Цитата Сообщение от programina Посмотреть сообщение
в Линуксе не правильно отображались данные заголовка .bmp рисунка
Дело в том, что они всеравно неправильно отображаются, потомучто при попытке открыть файл, кот. в виндовс отобразился правильно, в линуксе, отобразится неправильно.
0
Миниатюры
Использование #pragma pack(push,1)... pack(pop)   Использование #pragma pack(push,1)... pack(pop)  
Evg
Эксперт CАвтор FAQ
17808 / 6014 / 388
Регистрация: 30.03.2009
Сообщений: 16,525
Записей в блоге: 26
29.05.2012, 08:51 #37
Думаю, что у тебя 32-битная винда и 64-битный линукс. Либо наоборот. В таких случаях когда видишь разные результаты, то первым делом надо смотреть за использованием типа long, т.к. он 32-битный в режиме 32 и 64-битный в режиме 64. Вообще для программы, которая должна работать в режиме 32 и 64, описывая одинаково оду и ту же структуру данных, использование long'а недопустимо. Вернее, использовать можно, но только под макросами

Добавлено через 1 минуту
В печать помимо полей нужно распечатать sizeof твоей структуры

Добавлено через 38 минут
Один из способов выяснения смещений полей внутри структуры - это использование макроса, обычно его называют OFFSETOF (или всякие вариации на эту тему типа __OFFSETOF, __offsetof и т.п.). Результатом работы макроса будет байтовое смещение заданного поля внутри заданной структуры или объединения

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
#include <stdio.h>
 
#define OFFSETOF(_type, _field) \
 ((int) (((char*)&((_type *)0)->_field) - ((char*)0)))
 
struct s1
{
  short x;
  int y;
  char z;
};
 
struct s2
{
  char a;
  struct s1 b;
};
 
 
int
main (void)
{
  printf ("%d\n", OFFSETOF (struct s1, x));
  printf ("%d\n", OFFSETOF (struct s1, y));
  printf ("%d\n", OFFSETOF (struct s1, z));
 
  printf ("%d\n", OFFSETOF (struct s2, a));
  printf ("%d\n", OFFSETOF (struct s2, b));
  printf ("%d\n", OFFSETOF (struct s2, b.x));
  printf ("%d\n", OFFSETOF (struct s2, b.y));
  printf ("%d\n", OFFSETOF (struct s2, b.z));
 
  return 0;
}
1
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
29.05.2012, 11:20 #38
Evg, спасибо большое, у меня действительно 32-битный виндовс 7 и 64-битный линукс минт (вы телепат?)

PS: обязательно оставлю отзыв, но чуть позже
PPS: сижу значит в блогах и читаю всякие записи, и попадается мне ваша запись про директивы, но там еще не написано про #pragma, уже хотела оставить коммент с просьбой рассказать про эту прагму, но в последний момент передумала и зашла в гугл, который выдал эту тему
0
Evg
Эксперт CАвтор FAQ
17808 / 6014 / 388
Регистрация: 30.03.2009
Сообщений: 16,525
Записей в блоге: 26
29.05.2012, 11:25 #39
Цитата Сообщение от programina Посмотреть сообщение
вы телепат?
Это называется "experience". Когда наступаешь на грабли, то потом их видишь издалека

Цитата Сообщение от programina Посмотреть сообщение
запись про директивы, но там еще не написано про #pragma
Статья про препроцессорные директивы. #pragma к ним не относится
1
novi4ok
551 / 504 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
29.05.2012, 11:27 #40
теперь все ясно. но я бы, если бы передо мной стояла такая задача, начал бы не с того, чтобы "немножко подумать", а с того, "как бы это увидеть". т.е. создал бы такую структуру в обеих системах и вывел бы memory dump. и все увидел бы очень быстро.
0
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
29.05.2012, 17:20 #41
Заменила все 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;
}
0
Миниатюры
Использование #pragma pack(push,1)... pack(pop)   Использование #pragma pack(push,1)... pack(pop)  
Evg
Эксперт CАвтор FAQ
17808 / 6014 / 388
Регистрация: 30.03.2009
Сообщений: 16,525
Записей в блоге: 26
29.05.2012, 17:36 #42
Цитата Сообщение от 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
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
29.05.2012, 18:01 #43
Цитата Сообщение от Evg Посмотреть сообщение
C
1
2
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
Работает. Теперь буду делать только так.
0
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1287 / 1221 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
31.05.2012, 10:57 #44
Цитата Сообщение от programina Посмотреть сообщение
превращает обычный рисунок в негатив
У тебя не правильные структуры: Высота может быть отрицательной.
Ну и в начале нужна проверка, что это 24 битная картинка.
0
BBatonB
1 / 1 / 0
Регистрация: 19.07.2013
Сообщений: 21
26.07.2013, 00:01 #45
Добавлю 3 комейки.
Еще не докопавшись до #pragma pack, решил, что (поскольку типы данных - ряд факториала) просто надо составлять структуры, помещая вверх самые объемные типы... и вниз по убывающей. А в конце ставить "пустой" член структуры, дополняющий размер структуры до размера, кратного размеру наибольшего типа.
В редких случаях, когда структура состит всего из двух членов, один из которых имеет тип максимального размера, а другой - минимального, "потери" памяти будут ощутимы.(реальных программ, в которых это может сказаться - еще меньше)
В большинстве же случаев они будут ничтожны. Зато хорошая скорость и гарантия не столкнуться с одной проблемой.

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

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

Добавлено через 10 минут
А лучше всего было бы выбирать размер типов данных самому... из некоторого набора.
А может это возможно?
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.07.2013, 00:01
Привет! Вот еще темы с ответами:

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
26.07.2013, 00:01
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru