LINUX.ORG.RU

Размер и выравнивание

 ,


0

3

Добрый вечер.

struct S
{
char a;
double b;
}

std::cout << sizeof(S) << std::endl;// Выдает 16

std::cout << sizeof(char) + sizeof(double)<< std::endl;// Выдает 9

std::cout << alignof(S) << std::endl;// Выдает 8

Объясните, пожалуйста, как получаются 16, 9 и 8?

Ну 9 легко получается, так как размеры char и double у меня 1 и 8 соответственно.

Насчет 16-и : дело, наверное в размере машинного слова, которое наверняка 4 байта, однако double и char по логике должны 3 машинных слова занимать - 12 байт, откуда 16 взялись? Впечатление такое, что 16 как наименьшее общее кратное 4-х(машинного слова) и 8-и.

С выравниванием мне вообще малопонятно, разве нельзя любую структуру выровнять по размеру машинного слова данной машины (т.е. скорее всего 4 байта)?

Объясните, пожалуйста, как получаются 16, 9 и 8?

16 = 8 + 8;
9 = 1 + 8;
8 = const;

как-то так.

С выравниванием мне вообще малопонятно, разве нельзя любую структуру выровнять по размеру машинного слова данной машины (т.е. скорее всего 4 байта)?

Выравниваются переменные внутри структуры на соответствующие границы адресов.

asaw ★★★★★
()
Последнее исправление: asaw (всего исправлений: 1)

тупенький женек не осили прочитать про выравнивание структур и паддинг?

anonymous
()

OMG! ну вы хоть книжки то читайте!

16 потому что структура выравнена по 8, потому что double = 8

char - 1 байт double 8 байт = 9

anonymous
()

Но так или иначе структура не будет занимать 9 байт из-за длинны машинного слова?

Zhenek91
() автор топика

Царя! Вносите!

anonymous
()
Ответ на: комментарий от anonymous

читай про гранулярность доступа к памяти на твоей архитектуре и спрашивай тут только в крайних случаях

/thread

anonymous
()
Ответ на: комментарий от Kiborg

Да, возможно так точнее (автор же не сказал что у него за архитектура).

asaw ★★★★★
()

Размер не важен, вы все врете! :(

anonymous
()
Ответ на: комментарий от Kiborg

А чего, собственно, удивительного? Вот если бы там два char'а было, тогда был бы смысл их тасовать.

asaw ★★★★★
()
Ответ на: комментарий от Zhenek91

Да я уже сам проверил. Действительно, структура добивается «пустыми» полями до размера, кратного размеру максимального поля структуры. В данном случае sizeof(double) = 8, и поэтому суммарный размер структуры = наименьшее кратное 8, большее либо равное 8 + 1, независимо от порядка полей.

А вот если взять три поля, получается вот что:

kiborg@minton ~/test/cpp_struct_align $ cat test.cpp
#include <iostream>

struct S {
	char a;
	double d;
	char c;
};
struct D {
	char a;
	char c;
	double d;
};

int main(void)
{
	std::cout << sizeof (S) << std::endl;
	std::cout << sizeof (D) << std::endl;
	std::cout << alignof(S) << std::endl;
	std::cout << alignof(D) << std::endl;
	return 0;
}
kiborg@minton ~/test/cpp_struct_align $ g++ --std=c++11 test.cpp -o test
kiborg@minton ~/test/cpp_struct_align $ ./test
24
16
8
8
kiborg@minton ~/test/cpp_struct_align $ 

Kiborg ★★★
()
Ответ на: комментарий от Kiborg

Так то да, но интересно, что если

struct S
{
char array[6];
}

std::cout << sizeof(array) << std::endl;
// Выдает 6, хотя 6 байт должны вмещаться только в двух машинных словах - 8 байтах.

Хотя я не все понимаю в плане чтения компьютером памяти. Вот есть, например, адреса памяти (к примеру) от какого-нибудь 1024-го до 2048-го (типа килобайт памяти). Раз процессор работает только с машинными словами, это значит:

а) могут читаться ТОЛЬКО области памяти 1024-1027, 1028-1031,1032-1035,.....2044-2047.

б) могут читаться любые 4-байтные куски 1025-1028, 1031-1034,...

Вот какой вариант правильный : а или б?

Zhenek91
() автор топика
Ответ на: комментарий от Zhenek91

Раз процессор работает только с машинными словами, это значит

Процессор работает с кэш-линиями (cache line). У современных интелов это 64 байта. Собственно, смысл всех этих выравниваний в том, чтобы переменная ни при каких условиях не пересекала границу кэш-линий. Потому что если пересекает, то это будет два запроса к памяти вместо одного.

Relan ★★★★★
()
Ответ на: комментарий от Zhenek91

а) правильный

Смысл этих выравниваний чтобы операции чтения/записи переменных были атомарными. Ну и ещё некоторые архитектуры (MIPS например) в принципе не умеют работать с некоторыми типами, если они не выровнены - генерируется ошибка. char выравнивается на границу байта потому что этому типу всё равно куском какого минимального размера и с какой границы его прочтут - все равно это будет сделано за 1 раз. А к массиву доступ осуществляется поэлементно, собственно, как и к массивам структур (из-за чего они и добиваются в конце пустыми полями, если необходимо). Последнее не значит, что структуры читаются/записываются целиком.

asaw ★★★★★
()
Последнее исправление: asaw (всего исправлений: 2)
Ответ на: комментарий от Zhenek91

не все понимаю в плане чтения компьютером памяти

Ссылку на википедию уже давали выше.

а или б?

N-байтовые типы куски памяти (N=1,2,4,8) могут читаться процессором быстро, только если они находятся на адресах, кратных N. То есть один байт (условно, в регистр al) можно считать из памяти по любому адресу, два байта (ax) по четным адресам, и т. д. В x86, по-моему, читать можно по любым адресам, в т. ч. некратным, но это будет в разы медленнее.

Поэтому в структурах для увеличения быстродействия данные располагаются по выровненным адресам. То есть если «char c» попал на адрес 0xfff0, то следующий за ним «double d» будет начинаться с адреса 0xfff8, т. к. это наименьший адрес, кратный sizeof(double). Адреса 0xfff1-0xfff7 будут «заполнителем» (по факту, скорее всего, там просто будет мусор).

Кроме того, структура по умолчанию также дополняется в конце такими же бесполезными пустыми байтами до границы, кратной максимальному размеру данных в этой структуре. Это сделано для ускорения доступа к данным в массивах из таких структур. Поэтому struct A { char c[6] ; } и struct b {int32_t p; char c[2]; } имеют разный sizeof(): у последней присутствует поле типа int32_t, требующее выравнивания по 4 байтам, и поэтому структура будет занимать наименьшее кратное 4, то есть 8 байт.

Kiborg ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.