С Новым годом! Форум программистов, компьютерный форум, киберфорум
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. Показов 90134. Ответов 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
2343 / 499 / 22
Регистрация: 01.04.2009
Сообщений: 2,200
28.11.2009, 08:12
Лучший ответ Сообщение было отмечено как решение

Решение

почему автор не рекомендует:
http://www.kalinin.ru/programm... 7_00.shtml
если совсем коротко, то это директивы выравнивания данных.
и если их более одной в проекте, возможны накладки, когда одна и та-же структура данных будет иметь разное представление в памяти.

не надо извращаться.
гарантированно работает только то, что сделаешь сам.
без всяких "супердеректив".
4
Айхрень...
 Аватар для Paulie
306 / 176 / 7
Регистрация: 02.06.2009
Сообщений: 1,077
28.11.2009, 13:54  [ТС]
Получается, что единственно реальным и надёжным остаётся способ записи в файл структур - это запись отдельно каждого элемента структуры? Хм...
0
2343 / 499 / 22
Регистрация: 01.04.2009
Сообщений: 2,200
28.11.2009, 14:04
да.
для каждой сохраняемой структуры/класса лучше делаю собственные функции сохранения/восстановления.
причем, если программу планируется когда либо переносить на другой компилятор(например, VS 2008 вместо VS 6), то очень желательно еще и принудительно ограничивать размеры переменных.
потому, что размер int, например, может варьироваться от 16 до 64 бит, в зависимости от компилятора и его настроек.
и одна и та-же программа, скомпилированная в разных компиляторах, создаст тебе файлы разного размера.
3
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
28.11.2009, 14:21
Лучший ответ Сообщение было отмечено как решение

Решение

> и если их более одной в проекте, возможны накладки, когда одна и та-же структура данных будет иметь разное представление в памяти.

Ерунда всё это. Для того и сделаны директивы push и pop, чтобы работали вложенные случаи. Если эти директивы лепить непосредственно до и после описания одной структуры, то всё будет нормально. Если начать извращаться типа push написать в одном месте файла, дальше идёт описание 30 структур, между которым ещё торчит какой-то #include - то да, есть все шансы для того, чтобы в разных файлах описание одной и той же структуры подцепилось в разной форме. Работа с данными директивами концептуально ничем не отличается от работы с указателями: в умелых руках это мощный инструмент, а в кривых руках очередной способ развалить работу программы

Добавлено через 56 секунд
Если я непонятно выразился про "между которым ещё торчит какой-то #include" - могу для наглядности пример сделать
12
2343 / 499 / 22
Регистрация: 01.04.2009
Сообщений: 2,200
28.11.2009, 14:27
Цитата Сообщение от Evg Посмотреть сообщение
в умелых руках это мощный инструмент, а в кривых руках очередной способ развалить работу программы
может и так...
просто не знаю ни одного примера, где применение #pragma pack давало бы сколько-то значимый результат.
если уж оптимизировать структуры и работу программы - то лучше всю целиком, через опции компилятора.
ИМХО.
2
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
28.11.2009, 14:34
Лучший ответ Сообщение было отмечено как решение

Решение

А вопрос не в оптимизации структуры. Вопрос в том, чтобы правильно расписать структуру, чтобы она один в один ложилась на формат бинарного файла. Т.е. если в бинарном файле заголовок состоит из трёх полей размерами в один, четыре и два байта, идущих подряд друг за другом, то можно написать структуру

C
1
2
3
4
5
6
7
8
#pragma pack (push, 1)
struct
{
  char f1;
  int f2;
  short f3;
};
#pragma pack (pop)
и потом целиком экземпляр этой структуры одной операцией записывать или считывать в файл. sizoef от такой структуры будет равен 7. Стандартными средствами языка по-нормальному ты это не сделаешь. Можно только описать структуру, а потом читать-писать каждое поле в отдельности
9
2343 / 499 / 22
Регистрация: 01.04.2009
Сообщений: 2,200
28.11.2009, 15:17
Цитата Сообщение от Evg Посмотреть сообщение
Стандартными средствами языка по-нормальному ты это не сделаешь. Можно только описать структуру, а потом читать-писать каждое поле в отдельности
может быть, может быть...
но помнится мне, делал я как-то программку анализа звука.
считывал и разбирал wav-файлы.
читал просто кусок файла в буфер, определял указатель на структуру, идентичную структуре файла, и приравнивал ее к указателю на буфер.
и работал со структурой через указатель прямо в буфере.
и записывал обратно так-же.
накладок не было.
но это без #pragma pack, естественно.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
28.11.2009, 15:28
В твоём случае структуру можно было определить нормально, т.к. она без "дырок", обусловленных выравниванием. В указанной выше структуре в стандартном случае будут дырки, а потому без упакованных структур тут ничего не сделаешь (имеется в виду по простому)
2
2343 / 499 / 22
Регистрация: 01.04.2009
Сообщений: 2,200
28.11.2009, 15:39
Цитата Сообщение от Evg Посмотреть сообщение
В указанной выше структуре в стандартном случае будут дырки
проверил твою структуру.
VS 6.
работает.
выравнивание - 1 байт.
без #pragma pack.

... в общем вывод - все от рук зависит.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
28.11.2009, 15:55
Лучший ответ Сообщение было отмечено как решение

Решение

> выравнивание - 1 байт.

Стесняюсь спросить, и каким это образом ты проверил?

Добавлено через 2 минуты
И, собственно, не совсем понятно, при чём тут вообще выравнивание структуры, когда мы говорим о распределении полей в структуре?

C
1
2
3
4
5
6
7
8
9
10
11
#pragma pack (push, 1)
struct
{
  char f1;
  int f2;
  short f3;
} s;
#pragma pack (pop)
printf ("%d\n", ((char*)&s.f1) - (char*)&s);
printf ("%d\n", ((char*)&s.f2) - (char*)&s);
printf ("%d\n", ((char*)&s.f3) - (char*)&s);
Добавлено через 5 минут
Или, что более ближе к данной теме, вот такой пример:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma pack (push, 1)
struct s
{
  unsigned char f1;
  unsigned  int f2;
  unsigned  short f3;
};
#pragma pack (pop)
 
/* Этот буфер нам по сути дела заменяет файл */
char buff[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
                0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
struct s *p = (struct s*) buff;
 
printf ("%x\n", p->f1);
printf ("%x\n", p->f2);
printf ("%x\n", p->f3);
Печать для упакованной структуры

Code
1
2
3
11
55443322
7766
Печать для обычной структуры

Code
1
2
3
11
88776655
aa99
6
2343 / 499 / 22
Регистрация: 01.04.2009
Сообщений: 2,200
28.11.2009, 15:58
Цитата Сообщение от Evg Посмотреть сообщение
И, собственно, не совсем понятно, при чём тут вообще выравнивание структуры
Извини за глупый вопрос... но ЧТО по твоему означает параметр "1" в строке #pragma pack (push, 1)??
Я вообще перестаю понимать, о чем ты тогда пишешь.

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

лучше прочитай статью по ссылке из поста #2.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
28.11.2009, 16:22
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от Patch Посмотреть сообщение
Извини за глупый вопрос... но ЧТО по твоему означает параметр "1" в строке #pragma pack (push, 1)??
Означает максимальное выравнивание полей структуры (а не объекта). Если в случае обычной структуры все поля внутри неё выравниваются на выравнивание базового типа поля, то при наличии #pragma pack это выравнивание ограничивается. В случае единицы все поля структуры будут идти впритык друг к другу без выравниваний

Цитата Сообщение от Patch Посмотреть сообщение
а метод проверки - стандартный:
сделал файл, записал, считал, дебаггером посмотрел процесс.
Можно и с файлом. Но проще с массивом байтов (что принципиально от файла не отличается). В посте 11 я привёл конкретный пример - попробуй запусти его, так проще будет понять, в чём отличие

Цитата Сообщение от Patch Посмотреть сообщение
лучше прочитай статью по ссылке из поста #2.
Конкретно для себя я там ничего полезного нашёл. При чём уже не в первый раз вижу, что человек предлагает альтернативный вариант в виде шаблонов Си++, который без поллитры фиг разберёшь, лишь бы избежать этой несчастной pragm'ы. А можно не умничать а ВСЕГДА директивы ставить перед и после описания структуры. Если у тебя 10 структур с таким свойством - не поленись и 10 раз напиши pgarm'ы (ты же не поленился 10 раз написать структуру)

Добавлено через 2 минуты
Кстати, разработчики gcc сделали более правильный вариант - атрибут структуры __attribute__((packed (<value>))), с которым нет такой возможности накосячить, как с pragm'ой. При этом поддержали вариант pragma pack push/pop
5
2343 / 499 / 22
Регистрация: 01.04.2009
Сообщений: 2,200
28.11.2009, 16:45
хм... да не о том речь...
я знаю в чем отличие.
1)см. первый авторский пост - речь шла о работе с файлами.
2)мне не хватает фантазии представить программу, у которой часть структур будет выровнена на 1 байт, а часть - на 2/4, так, чтобы это значимо сказывалось на скорости исполнения.
ну, если ты пишешь программу, работающую быстро - оптимизируй на скорость и выравнивай на 2/4;
если мало места - оптимизируй на экономичность и выравнивай на 1 байт;
на кой фиг нужна директива, меняющая выравнивание отдельно взятой структуры - ума не приложу.
единственный вариант, который приходит в голову - это База данных, но...
там ПРИХОДИТСЯ выравнивать структуры в файле на 1 байт, иначе диска не хватит.
а чтобы еще и в памяти доступ быстро шел приходится писать СОБСТВЕННЫЕ функции считывания/записи, т.к. в этом случае данные в памяти и в файле хранятся в немного разных форматах.
вот и получается...
нафиг эта директива не нужна, а для сохранения/восстановления структур лучше делать собственные функции.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
28.11.2009, 18:04
Лучший ответ Сообщение было отмечено как решение

Решение

1)см. первый авторский пост - речь шла о работе с файлами
Именно поэтому автор и захотел использовать #pragm'ы. Потому что с ними код программы и его внутренняя архитектура сильно упрощается. Про оптимизации по скорости тут вообще речи не идёт. Давай поставлю проблему ближе к реальной задаче. В файле имеется заголовок, в котором определено количество записей и сами записи. Для простоты будем работать с байтовым массивом (потому что он принципиально от файла ничем не отличается), чтобы весь материал был заключён в одной программе, без дополнительных файлов с данными

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <stdio.h>
 
/* ------------------------------------------------------------- */
 
/* Заголовк: подряд идут 1 байт, 4 байта, 2 байта
 * В 4-байтном поле записано количество записей в файле */
#pragma pack (push, 1)
struct Hdr
{
  unsigned char f1;
  unsigned int num_entries;
  unsigned char f3;
};
#pragma pack (pop)
 
/* Запись: подряд идут 1 байт, 4 байта, 1 байт, 4 байта */
#pragma pack (push, 1)
struct Entry
{
  unsigned char f1;
  unsigned int f2;
  unsigned char f3;
  unsigned int f4;
};
#pragma pack (pop)
 
/* ------------------------------------------------------------- */
 
/* Буффер, эулирующий файл */
char FilBuff[] =
{
  /* Заголовок, в котором определены 2 записи */
  0x11,
  0x02, 0x00, 0x00, 0x00,
  0x22,
 
  /* Запись 1 */
  0xa0,
  0xa1, 0xa2, 0xa3, 0xa4,
  0xa5,
  0xa6, 0xa7, 0xa8, 0xa9,
 
  /* Запись 2 */
  0xb0,
  0xb1, 0xb2, 0xb3, 0xb4,
  0xb5,
  0xb6, 0xb7, 0xb8, 0xb9,
};
 
/* ------------------------------------------------------------- */
 
/* Моделируем работу с файлом, но будем работать с массивом */
typedef struct
{
  char *cur; /* тещущая позиция в файле (а в нашем случае в буффере) */
} MY_FILE;
 
MY_FILE*
my_fopen (void *p)
{
  static MY_FILE f;
  f.cur = (char*) p;
  return &f;
}
 
/* Чтение из файла f блока данных размером size в буффер buff */
void
my_fread (void *buff, int size, MY_FILE *f)
{
  int i;
  char *dst = (char*) buff;
  
  /* Моделирем побайтное чтение с перемоткой позиции в файле */
  for (i = 0; i < size; i++)
    *dst++ = *(f->cur++);
}
 
/* ------------------------------------------------------------- */
 
int
main (void)
{
  MY_FILE *f;
  struct Hdr hdr;
  struct Entry entry;
  int i;
 
  /* Открываем файл */
  f = my_fopen (FilBuff);
 
  /* Читаем заголовок */
  my_fread (&hdr, sizeof (hdr), f);
 
  printf ("Hdr.f1=%x\n", hdr.f1);
  printf ("Hdr.num_entries=%x\n", hdr.num_entries);
  printf ("Hdr.f3=%x\n", hdr.f3);
 
  /* Читаем записи */
  for (i = 0; i < hdr.num_entries; i++)
    {
      my_fread (&entry, sizeof (entry), f);
      printf ("------\n");
      printf ("Entry %d\n", i);
      printf ("f1=%x\n", entry.f1);
      printf ("f2=%x\n", entry.f2);
      printf ("f3=%x\n", entry.f3);
      printf ("f4=%x\n", entry.f4);
    }
 
  return 0;
}
Вот такая получается выдача

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Hdr.f1=11
Hdr.num_entries=2
Hdr.f3=22
------
Entry
f1=a0
f2=a4a3a2a1
f3=a5
f4=a9a8a7a6
------
Entry
f1=b0
f2=b4b3b2b1
f3=b5
f4=b9b8b7b6
А теперь попробуй сделать то же самое (ну или модифицировать программу), чтобы работало без директивы pragma. И сравни, какой вариант окажется проще

Добавлено через 53 секунды
> на кой фиг нужна директива, меняющая выравнивание отдельно взятой структуры - ума не приложу

Ещё раз для тех кто в танке. Не "выравнивание структуры", а "выравнивания полей структуры". Ты отличаешь эти понятия?

Добавлено через 2 минуты
> нафиг эта директива не нужна, а для сохранения/восстановления структур лучше делать собственные функции.

Делай. Только при любом изменении во внутренности структуры тебе придётся модифицировать твои процедуры чтения/записи
3
2343 / 499 / 22
Регистрация: 01.04.2009
Сообщений: 2,200
28.11.2009, 18:37
Цитата Сообщение от Evg Посмотреть сообщение
Потому что с ними код программы и его внутренняя архитектура сильно упрощается. Про оптимизации по скорости тут вообще речи не идёт.
ну е-мое... еще раз: ставь выравнивание в 1 байт на всю программу и получишь тот-же результат.
Цитата Сообщение от Evg Посмотреть сообщение
Ещё раз для тех кто в танке. Не "выравнивание структуры", а "выравнивания полей структуры". Ты отличаешь эти понятия?
для тех кто в танке - я говорю о выравнивании структуры данных, а не конкретного объекта с/с++ типа struct. ТЫ отличаешь эти понятия?
Цитата Сообщение от Evg Посмотреть сообщение
Делай. Только при любом изменении во внутренности структуры тебе придётся модифицировать твои процедуры чтения/записи
Да. Если структура в файле отличается от структуры в памяти.
Иначе - я напишу Write(..., &struct xxx, sizeof(xxx)).
что в твоем пример, что нет... ну НЕТ разницы.

только без #pragma жить проще.
1
Айхрень...
 Аватар для Paulie
306 / 176 / 7
Регистрация: 02.06.2009
Сообщений: 1,077
28.11.2009, 22:29  [ТС]
Ребята, Ваши рассуждения очень интересны и полезны, пожалуй. что не только мне, спасибо огромное! Можете, конечно, продолжить

А вот такой вопрос возник по ходу ваших рассуждений, если взять проекцию на Делфи, то диреткива #pragma pack делает что-то наподобие, как и record packed в Делфи? Или второе - это выравнивание структуры, а в сях - выравнивание полей, как сказал уважаемый Evg, ну это так, чисто интерес, вспомнилось былое прошлое...
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
28.11.2009, 22:38
Цитата Сообщение от Patch Посмотреть сообщение
ну е-мое... еще раз: ставь выравнивание в 1 байт на всю программу и получишь тот-же результат
Что такое выравнивание 1 байт на всю программу?

Цитата Сообщение от Patch Посмотреть сообщение
для тех кто в танке - я говорю о выравнивании структуры данных, а не конкретного объекта с/с++ типа struct. ТЫ отличаешь эти понятия?
Что такое выравнивание структуры данных? И вообще, что такое структура данных? При чём тут конкретный объект Си\Си++ (и вообще, где ты этот объект откопал)? Эти понятия я навряд ли отличаю, потому как не втыкаю, про что ты говоришь. И о чём ты там говоришь тоже салабо понимаю, а я говорю конкретно о вопросе, поставленном в данной теме

Цитата Сообщение от Patch Посмотреть сообщение
Да. Если структура в файле отличается от структуры в памяти
Если бы да кабы. Речь идёт о случае, когда отличаются

Цитата Сообщение от Patch Посмотреть сообщение
только без #pragma жить проще
Я в 15-м посте сделал тебе конкретное предложение переписать программу без pragm'ы, на которое кроме невнятного ответа про "выравнивание на всю программу" так ничего и не получил
2
11 / 11 / 2
Регистрация: 18.07.2009
Сообщений: 123
11.04.2011, 16:09
знакомый драйверист железячник говорил, что при работе с железками и сетью прям обязательно нужно выравнивать по 1 байту, а сам я раньше по сети слал без выравнивания, а теперь вот наткнулся на топик :-)
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
11.04.2011, 17:30
Цитата Сообщение от __beginner__ Посмотреть сообщение
что при работе с железками и сетью прям обязательно нужно выравнивать по 1 байту
Вообще говоря, любой адрес выровнен на 1 байт. А твои слова сильно смахивают на испорченный телефон. Не говоря уж о том, что напрямую с железками работает только ОС, а не пользовательская программа
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
11.04.2011, 17:30
Помогаю со студенческими работами здесь

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?...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru