Сколько занимает структура в памяти
Здравствуйте, ktin, Вы писали:
K>Структура состоит из Value-типов.
K>Нужно узнать её размер.
K>Подскажите как это сделать (ручками пересчитывать разные value-типы, умножая на их размерность в байтах — не катит)
Здравствуйте, VladGalkin, Вы писали:
VG>Здравствуйте, ktin, Вы писали:
K>>Структура состоит из Value-типов.
K>>Нужно узнать её размер.
K>>Подскажите как это сделать (ручками пересчитывать разные value-типы, умножая на их размерность в байтах — не катит)
VG> не катит?
Доступно только в unsafe
Здравствуйте, krasin, Вы писали:
VG>> не катит?
K>Доступно только в unsafe
Здравствуйте, VladGalkin, Вы писали:
дополнение — нужно узнать размер экземпляра структуры, заполненной данными.
не подойдет. объясняю почему.
создаем экземпляр и заполняем.
ответ: 8 (указатель + int).
а хотелось бы получить размер строчки + int (в данном примере, по крайней мере)
з.ы. думалось в куче создавать структурку, потом разницу адресов смотреть — но это не thread safe получается.
Вы писали:
P_A>Marshal.SizeOf(структура); подойдет?
VG>Пардон, эт только для predefined types.
K>а необходимо найти размер живой структуры, заполненной данными.
Надеюсь, есть понимание, что эти данные вовсе не лежат рядом со структурой ни в каком смысле?
Если по-прежнему хочется именно такого размера, то считать придется руками.
Сомневаюсь что со строками это прокатит. Строки-то в хеше лежат.
В обратную сторону можно, например,
А вот чтобы просто sizeof.
Может от задачи пойти — типа зачем это надо и обойти другим путем.
Здравствуйте, Pavel_Agurov, Вы писали:P_A>Сомневаюсь что со строками это прокатит. Строки-то в хеше лежат.
Большинство строк лежат в куче. Некоторые -- в пуле.
Здравствуйте, ktin, Вы писали:
K>ага.
K>а необходимо найти размер живой структуры, заполненной данными.
Не хочу показаться излишне придирающимся к словам, но в вопросе ничего про необходимость safe не сказано.
Здравствуйте, Mab,
да,понимание есть.
поэтому то и спрашиваю(т.к. не знаю как считать).
Вы писали:
K>>а необходимо найти размер живой структуры, заполненной данными.
Mab>Надеюсь, есть понимание, что эти данные вовсе не лежат рядом со структурой ни в каком смысле?
Mab>Если по-прежнему хочется именно такого размера, то считать придется руками.
Здравствуйте, Pavel_Agurov,
а что этим кодом сделали?
описали структуру для Маршалинга в unmanaged код? (если да — то как это осуществляется?)
может это то что нужно?
задача: всю память, которую занимает данная структура передать библиотеке (с максимальной скоростью).
Вы писали:
P_A>Сомневаюсь что со строками это прокатит. Строки-то в хеше лежат.
P_A>В обратную сторону можно, например,
P_A>
P_A>А вот чтобы просто sizeof.
P_A>Может от задачи пойти — типа зачем это надо и обойти другим путем.
Здравствуйте, VladGalkin, Вы писали:
Можно, можно unsafe использовать! рад любому решению.
Только sizeof НЕ катит. ну не работает он.
Error: The type or namespace name 'z' could not be found (are you missing a using directive or an assembly reference?)
VG>Не хочу показаться излишне придирающимся к словам, но в вопросе ничего про необходимость safe не сказано.
Здравствуйте, ktin, Вы писали:
K>Можно, можно unsafe использовать! рад любому решению.
K>Только sizeof НЕ катит. ну не работает он.
K>
K>Error: The type or namespace name 'z' could not be found (are you missing a using directive or an assembly reference?)
Так это, как грицца проблема вовсе не в sizeof. Нормально он работает.
Компилировать с ключом /unsafe.
Здравствуйте, VladGalkin, Вы писали:
VG>
Конечно, первый unsafe можно удалить.
Здравствуйте, VladGalkin, Вы писали:
=) да нормально он работает, на predefined типов.
для ТИПОВ. не переменных.
(в том примере структура — 8 байт, но экземпляр будем много больше — строчка ещё сколько занимает)
вот.
VG>Так это, как грицца проблема вовсе не в sizeof. Нормально он работает.
VG>
VG>Компилировать с ключом /unsafe.
VG>Выводит:
VG>
Здравствуйте, ktin, Вы писали:
K>(в том примере структура — 8 байт, но экземпляр будем много больше — строчка ещё сколько занимает)
K>вот.
"Учится, учится и учится!" (С)
String это reference-тип, размер ссылки — 4 байта.
Здравствуйте, ktin, Вы писали:
K>(в том примере структура — 8 байт, но экземпляр будем много больше — строчка ещё сколько занимает)
Сдается, этого понимания таки нет.
вот именно.
а мне нужен размер "ВСЕГО хозяйства".
8 байт то я получу (как и писал ссылка — 4, Int -4 4+4=8) без проблем. =)))
мне они НЕ нужны.
Вы писали:
VG>String это reference-тип, размер ссылки — 4 байта.
Здравствуйте, VladGalkin, Вы писали:
Здравствуйте, ktin, Вы писали:
K>хорошо, давай я напишу следующим образом, если не понятно:
K>мне нужно узнать размер, который занимает структура, вместе с той памятью, которую занимают объекты(будь то массивы байт, чаров (наш стринг, ага?) или интов) по ссылкам (references) из структуры, независимо от того, где они лежат в памяти.
K>важен результат — СКОЛЬКО.
K>хорошо, давай я напишу следующим образом, если не понятно:
K>мне нужно узнать размер, который занимает структура, вместе с той памятью, которую занимают объекты(будь то массивы байт, чаров (наш стринг, ага?) или интов) по ссылкам (references) из структуры, независимо от того, где они лежат в памяти.
K>важен результат — СКОЛЬКО.
Ты бы сказал зачем это нужно? Тот же string, по крайней мере, после StringBuilder имеет разное количество байт в памяти и количество символов.
Здравствуйте, ktin, Вы писали:
K>Структура состоит из Value-типов.
K>Нужно узнать её размер.
K>Подскажите как это сделать (ручками пересчитывать разные value-типы, умножая на их размерность в байтах — не катит)
Сериализовать структуру BinaryFormatter`ом и вычислить изменение длины стрима.
. << RSDN@Home 1.2.0 alpha rev. 650>>Now playing: «Тихо в лесу…» Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, ktin, Вы писали:
K>дополнение — нужно узнать размер экземпляра структуры, заполненной данными.
K>не подойдет. объясняю почему.
K>существует структура
Now playing: «Тихо в лесу…» Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, GlebZ, Вы писали:
написал.
задача: всю память, которую занимает данная структура передать библиотеке (с максимальной скоростью), чтобы этот "образ" там хранить, или записать в файл (буквально таки сериализация).
GZ>Ты бы сказал зачем это нужно? Тот же string, по крайней мере, после StringBuilder имеет разное количество байт в памяти и количество символов.
Здравствуйте, VladGalkin,
тобишь твой ответ — никак без ручек?
Здравствуйте, _FRED_, Вы писали:
_FR>Сериализовать структуру BinaryFormatter`ом и вычислить изменение длины стрима.
Если мне не изменяет память BinaryFormatter сохряняет также информацию о типах сохраняемых данных. Так что твоя реккомендация к желаемому результату не приведет.
Marshal.Sizeof() прекрасно работает и со строками, и с массивами, и с вложенными структурами. Для массивов надо использовать атрибут [MarshalAs(UnmanagedType.ByValArray, SizeConst = )]. Проверялось при создании своей сериализации данных. Структуры, кстати, объявлялись с атрибутом: [StructLayout(LayoutKind.Sequential, Pack = 1)] .
Кстати, с каких пор string стал value-типом? А последний пример вполне адекватен для указанной задачи. Как раз так и делали, используя и другие члены Marshal.
Размер памяти, занимаемый структурным объектом, можно вычислить, исходя из размеров элементов структуры либо с помощью операции :
Определение структурного типа не связано с выделением памяти под сам тип, а при каждом определении структуры (объекта) ей выделяется память в таком количестве, чтобы могли разместиться данные всех элементов. Однако стандарт языка С++ не дает гарантий, что элементы структур будут размещаться непрерывно. Причиной появления неиспользованных участков памяти ("дыр") могут явиться требования выравнивания данных по границам участков адресного пространства . Эти требования зависят от реализации, от аппаратных возможностей системы и иногда от режимов (опций) работы компилятора.
sizeof(struct goods) – 24 байта (из Примера 1)
sizeof(goods) – 24 байта (из Примера 1)
sizeof coat – 24 байта (из Примера 1)
sizeof( complex ) – 16 байтов (из Примера 2)
Пример 3. Программа вывода размера памяти для структурного объекта
Результат выполнения программы:
Массивы структур
Массив структур – это массив , каждый элемент которого является структурой. В памяти элементы массива структур размещаются последовательно.
Массивы структур широко используются для структурной организации данных в прикладных программах и системном программном обеспечении.
Из элементов структурного типа можно организовать массивы также как из элементов стандартного типа. Для объявления массива структур следует сначала определить структуру, а затем объявить массив переменных данного типа. Как и массивы переменных, массивы структур индексируются с нуля.
Пример 4. Программа определяет и печатает название самой высокой вершины из списка
Пример 5. Программа инициализирует массив структур, сортирует и выводит его на печать .
Ключевые термины
Агрегатный тип данных – это тип, конструируемый из элементов независимых (возможно различных) типов.
Инициализирующая запись – это заключенный в фигурные скобки список , элементы которого разделяются запятыми и являются константами.
Массив структур – это массив , каждый элемент которого является структурой.
Поименованный шаблон – это одна из основных форм объявления структур, задаваемая именем структурного типа и определениями элементов.
Поля структуры – это составные части структуры, характеризующиеся именем, типом и размером.
Размер структуры – это объем памяти, занимаемой структурой.
Структура – это составной объект , в который входят элементы любых типов, за исключением функций.
Структура — это объединение нескольких объектов, возможно, различного типа под одним именем, которое является типом структуры. В качестве объектов могут выступать переменные, массивы, указатели и другие структуры.
Структуры позволяют трактовать группу связанных между собой объектов не как множество отдельных элементов, а как единое целое. Структура представляет собой сложный тип данных, составленный из простых типов.
Общая форма объявления структуры:
тип ИмяЭлемента1;
тип ИмяЭлемента2;
. . .
тип ИмяЭлементаn;
>;
После закрывающей фигурной скобки > в объявлении структуры обязательно ставится точка с запятой.
Пример объявления структуры
int day; // 4 байта
char *month; // 4 байта
int year; // 4 байта
>;
Поля структуры располагаются в памяти в том порядке, в котором они объявлены:
В указанном примере структура date занимает в памяти 12 байт. Кроме того, указатель *month при инициализации будет началом текстовой строки с названием месяца, размещенной в памяти.
При объявлении структур, их разрешается вкладывать одну в другую.
struct personechar lastname[20]; // фамилия
char firstname[20]; // имя
struct date bd; // дата рождения
>;
Инициализация полей структуры
Инициализация полей структуры может осуществляться двумя способами:
- присвоение значений элементам структуры в процессе объявления переменной, относящейся к типу структуры;
- присвоение начальных значений элементам структуры с использованием функций ввода-вывода (например, printf() и scanf() ).
В первом способе инициализация осуществляется по следующей форме:
Имя элемента структуры является составным. Для обращения к элементу структуры нужно указать имя структуры и имя самого элемента. Они разделяются точкой:
Второй способ инициализации объектов языка Си с использованием функций ввода-вывода.
12
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
Имя структурной переменной может быть указано при объявлении структуры. В этом случае оно размещается после закрывающей фигурной скобки > . Область видимости такой структурной переменной будет определяться местом описания структуры.
double real;
double imag;
> number; // имя структурной переменной
Поля приведенной структурной переменной: number.real, number.imag .
Объединения
Объединениями называют сложный тип данных, позволяющий размещать в одном и том же месте оперативной памяти данные различных типов.
Размер оперативной памяти, требуемый для хранения объединений, определяется размером памяти, необходимым для размещения данных того типа, который требует максимального количества байт.
Когда используется элемент меньшей длины, чем наиболее длинный элемент объединения, то этот элемент использует только часть отведенной памяти. Все элементы объединения хранятся в одной и той же области памяти, начиная с одного адреса.
Общая форма объявления объединения
тип ИмяОбъекта1;
тип ИмяОбъекта2;
. . .
тип ИмяОбъектаn;
>;
Объединения применяются для следующих целей:
- для инициализации объекта, если в каждый момент времени только один из многих объектов является активным;
- для интерпретации представления одного типа данных в виде другого типа.
Например, удобно использовать объединения, когда необходимо вещественное число типа float представить в виде совокупности байтов
Пример Поменять местами два младших байта во введенном числе
Битовые поля
Используя структуры, можно упаковать целочисленные компоненты еще более плотно, чем это было сделано с использованием массива.
Набор разрядов целого числа можно разбить на битовые поля, каждое из которых выделяется для определенной переменной. При работе с битовыми полями количество битов, выделяемое для хранения каждого поля отделяется от имени двоеточием
При работе с битовыми полями нужно внимательно следить за тем, чтобы значение переменной не потребовало памяти больше, чем под неё выделено.
Пример Разработать программу, осуществляющую упаковку даты в формат
Массивы структур
Работа с массивами структур аналогична работе со статическими массивами других типов данных.
Пример Библиотека из 3 книг
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
Указатели на структуры
Доступ к элементам структуры или объединения можно осуществить с помощью указателей. Для этого необходимо инициализировать указатель адресом структуры или объединения.
Для организации работы с массивом можно использовать указатель. При этом обращение к полям структуры через указатель будет выглядеть как:
указатель — указатель на структуру или объединение;
поле — поле структуры или объединения;
Динамическое выделение памяти для структур
Динамически выделять память под массив структур необходимо в том случае, если заранее неизвестен размер массива. Для определения размера структуры в байтах используется операция sizeof (ИмяСтруктуры) .
Пример Библиотека из 3 книг
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
Результат выполнения аналогичен предыдущему решению. Здравствуйте! Спасибо Вам за статью. Мне непонятен доступ к элементам структуры когда одним из элементов является массив. Например есть структура struct book <
char massiv[20];
int b [5];
char c;
>;
struct book lolik;
Мы можем проинициализировать поля структуры только при ее объявлении. Дальше уже идут операции присваивания. Причем инициализация должна быть выполнена для всех полей одновременно. Нельзя проинициализировать часть полей (причем из середины). Можно сделать так: Здравствуйте. Подскажите, как при задании массива структур правильно инициализировать поля каждой структуры? Массив статический. Если можно, хотелось бы увидеть какие-нибудь примеры. Добрый вечер! Подскажите, пожалуйста, как вывести несколько департаментов, если количество сотрудников одинаковое и не вывести ничего, если не удовлетворяет заданию? Заранее спасибо! Задание: найти самый маленький отдел, созданный не позднее заданной даты Вроде все работает, но не понимаю, как написать условие (возможно, if, else), чтобы при одинаковом кол-ве сотрудников вывел оба департамента и чтобы не вывел ничего, если не удовлетворяет условию, связанным с годом? P.S. Структура задана в заголовочном файле ЗАГОЛОВОЧНЫЙ ФАЙЛ (department.h):
struct int amount; // количество сотрудников
char lastname[50]; // фамилия начальника
> inc;
struct int year;
int month;
> date;
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
void display( struct Office* a, int i) //вывод одного отдела с помощью цикла
printf( "Название: %s\nКоличество сотрудников: %d\nФамилия начальника: %s\nДата создания: %d.%d\n\n" ,
a[i].title, a[i].inc.amount, a[i].inc.lastname, a[i].date.year, a[i].date.month);
>
void create( struct Office* a, int * pn) //функция ввода с клавиутары данных и вывод их на консоль
printf( "Введите количество отделов (< 20): " );
scanf_s( "%d%*c" , pn); //%*c применяется для удаления enter и считывания fgets дальше (чтобы они работали и воспринимались программой)
printf( "\n" );
for ( int i = 0; i < *pn; i++)
printf( "Название: " );
fgets(a[i].title, 50, stdin);
a[i].title[strlen(a[i].title) - 1] = 0;
printf( "Количество сотрудников: " );
scanf_s( "%d%*c" , &a[i].inc.amount);
printf( "Фамилия начальника: " );
fgets(a[i].inc.lastname, 50, stdin);
a[i].inc.lastname[strlen(a[i].inc.lastname) - 1] = 0;
printf( "Дата создания: " );
scanf_s( "%d%d%*c" , &a[i].date.year, &a[i].date.month);
puts( "" );
>
>
int small( struct Office* a, int n, int year, int month)
<
int i = 0, index = 0, min = 0;
while ((a[i].date.year > year) || (a[i].date.month > month) && (a[i].date.year == year)) //сравниваем дату создания с датой, введенной нами
i++;
>
index = i;
min = a[i].inc.amount;
for (i; i < n; i++) //находим самый маленький отдел и сравниваем дату с другими датами создания отдела
if ((a[i].inc.amount < min) && (a[i].date.year <= year) || (a[i].inc.amount < min) && (a[i].date.month <= month) && (a[i].date.year == year))
min = a[i].inc.amount;
index = i;
>
>
return index;
>
int main()
setlocale(LC_ALL, "Rus" ); //включение локализации
setlocale(LC_NUMERIC, "Eng" ); //использование "." в дробных значениях
int n = 0, year = 0, month = 0;
n = sizeof (A) / sizeof (A[0]); //размер (в байтах) всего массива, то есть сумма всех элементов/ размер (в байтах) одной структуры (50)
for ( int i = 0; i < n; i++)
display(A, i);
printf( "Введите дату создания: " );
scanf_s( "%d%d%*c" , &year, &month);
printf( "\n" );
n = small(A, n, year, month);
display(A, n);
return 0;
>
Со структурами C++ мы предварительно познакомились в предыдущей статье. Продолжаем знакомство.
Определение структуры желательно располагать за пределами main() функции. Тогда работать с ней смогут и другие определенные программистом функции, как показано в нашем примере из первой части. Такое объявление называют внешним.
Инициализация. Элементы структуры можно инициализировать сразу при объявлении объекта.
Рассмотрим такую инициализацию на примере с более сложной структурой WonderfulWoman :
Объект этой структуры можно инициализировать так:
Но если структура содержит больше двух-трех элементов -желательно так не делать. Это немного запутывает и усложняет читаемость и понимание программы.
Объявление объектов. Создать объект структуры можно сразу во время её определения. Для этого необходимо дать имя объекту между точкой с запятой и закрывающей фигурной скобкой:
В С++ есть возможность определить структуру без дескриптора (без имени типа):
Присваивание ( = ) для структур. Для объектов одной структуры можно применить операцию присваивания = . Операция присвоит элементам одного объекта значения элементов второго объекта.
Это так называемое поэлементное или почленное присваивание. На экране:
Память занимаемая структурой. Рассмотрим пример: используя оператор sizeof , узнаем сколько памяти занимает каждый элемент структуры в отдельности. Посчитаем общий объем памяти элементов. Потом применим sizeof к объекту структуры и увидим, что размеры не совпадают.
cout << "sizeof(Man.name) crayon-h"> << sizeof ( Man . name ) << endl ; cout << "sizeof(Man.age) crayon-h"> << sizeof ( Man . age ) << endl ; cout << "sizeof(Man.height) crayon-h"> << sizeof ( Man . height ) << endl ; cout << "sizeof(Man.engKnowledge) crayon-h"> << sizeof ( Man . engKnowledge ) << endl ; cout << sizeof ( Man . name ) + sizeof ( Man . age ) + sizeof ( Man . height ) + sizeof ( Man . engKnowledge ) ;Мы узнали как определять структуры, как объявлять и инициализировать их объекты. Если нам понадобится создать больше чем 2-3 объекта структуры, тогда лучше создать массив структур. Эту тему рассмотрим в следующей статье.
6 thoughts on “ Структуры в C++. Часть 2 ”
Только структуру нужно было назвать PrettyWoman ;)
А кто вас учил такое вводить?
Где вы такое в примерах видели?
Дан массив, в котором хранятся данные о расписании поездов на сего-
дняшний день: номер поезда, название (т.е. откуда – куда, например, Ново-
российск-Москва), время прибытия на станцию и время отправления (часы,
минуты). По данному времени определить, какие из поездов стоят сейчас на
станции.
struct Grades // эту структуру мы вложим в структуру Student
int physics;
int maths;
int informatics;
int chemistry;
>;
struct Student
char surname[32];
int year_of_birth;
int number_of_groope;
Grades semester_grades; // вложенная структура(оценки за семестр)
double average_score;//средний балл
>;
void showData( Student *Obj);
void showData_input(Student *Obj);
>
void showData_input(Student *Obj)
setlocale(LC_ALL, "rus");
cout << "__________________" << endl;
cout << "Input student data" << endl;
cout << "__________________" << endl;
Чет опять без каких-либо пояснений вылезают новые термины и строки, особенно в видео этого много.
Читайте также: