Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.06.2013, 17:47   #1
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию Выравнивание

Здравствуйте!
Пытаюсь понять причины и цели выравнивание адресов. Запутался и не понимаю первопричин.
Читал про всякую гранулярность и т.д., но чувство такое, что авторы сами не до конца понимают и пишут только о верхушках.
Я бы хотел понять логику поведение своего железного друга в следующих случаях:
Код:
struct Ss	// Размер = 8
{
	int hh;
	char g;
};

struct S	// Размер = 4
{
	short hh;
	char g;
};
int main()
{
	long g;
	char b;
	cout<<( int(&g) % 8)<<"\n";		// Иногда 0, иногда 4
	cout<<( int(&b) % 4);		// 3
}
1. Почему в структурах размер предыдущего элемента влияет на размер следующего?
2. После прочтения некоторых статей, у меня сложилось мнение, что чтение из памяти возможно с определенных мест (кратных 2, …). Тогда почему адрес b не кратен даже двойки?
3. Раз b находится в таком ”неправильном” месте, значит процессору не особо важно откуда читать? А если так, то зачем он парится c ”правильным” расположением элементов в структурах выше?

Различные версии вроде меньшего количество инструкций конечно здорово, но не объясняет ничего.
Честно говоря, сомневаюсь, что получу полный и развернутый ответ, может кто-то посоветуют что-то для прочтения, буду признателен.
220Volt вне форума Ответить с цитированием
Старый 19.06.2013, 18:03   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Для 32 битных приложений адреса должны быть кратными 4. Явно старые статьи читаете.

Интеловские процессоры могут читать с "неправильных" адресов но делают это в два присеста, с двух соседний адресов, кратных 4. Например, при попытке прочитать 4 байта с адреса 2 процесор прочитает с адреса 0 четыре байта (и возьмет половину из них) а потом прочитает с адреса 4 еще 4 байта и из них возмет недостающие два и "вычислит" содержимое по адресу 2.

Первая проблема это быстродействие - читаем в два раза больше.
Вторая проблема это консистентност - имеем две операции а не одну и это уже не атомично.

Третья проблема несколько отдаленная - подавляющее большинство других процессоров (а то и все, кром интеловских) НЕ могут читать с некратных адресов.

Для чтения 1 и 2 байтов не обязательно всегда читать с кратного адреса - главное чтоб эти 1 или 2 байта умещались в процесорное слово (32 бит). Например если читаем 2 байта с адреса 2 то процесор делает это за один присест прочитав 4 байта с адреса 0 и отбрасывает лишнее.
waleri вне форума Ответить с цитированием
Старый 19.06.2013, 20:20   #3
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию

Спасибо. Но:
* Зачем структура Ss занимает 8 байт? Если она будет пять байт, количество чтений не изменится.
* Почему S 4 байта? Не понимаю в чем выгода? К чему набивать пустотой?
* Может это на случай создание массивов?
220Volt вне форума Ответить с цитированием
Старый 19.06.2013, 21:26   #4
eoln
Старожил
 
Аватар для eoln
 
Регистрация: 26.04.2008
Сообщений: 2,645
По умолчанию

Уже сказано, чтобы не читать с "неправильных" адресов. Если эти 2 структуры читаются друг за другом (они как раз 8 байт в сумме), то может ещё и ничего(если они не смещены), а если по отдельности(или они смещены), то для прочтении,например, второй структуры (размером 3 байта) может потребоваться 2 чтения (например, если она смещена на 2 байта от начала слова), что несколько дольше.
В данном случае идёт выравнивание кратное 4, в первом случае структура занимает 5 байт и выравнивается до 8. Если бы она занимала 6 или 7 байт, то тоже выравнивалось бы до 8. Вторая структура - 3 байта, выравнивается до 4.
"Пустоты", как уже было сказано, для быстроты и совместимости.
Если не нравится такой поворот событий, то можно изменить выравнивание в настройках компилятора или в коде с помощью дирректив.
eoln вне форума Ответить с цитированием
Старый 19.06.2013, 21:46   #5
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Полезная информация.
Вложения
Тип файла: pdf Slides2012-10.pdf (1.01 Мб, 14 просмотров)
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 19.06.2013, 21:54   #6
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Цитата:
Сообщение от 220Volt Посмотреть сообщение
* Почему S 4 байта? Не понимаю в чем выгода? К чему набивать пустотой?
Экономится место. В этой структуре нужны 2 + 1 байта для данных. Технически процессор будет читать обе переменные с одного адреса.
waleri вне форума Ответить с цитированием
Старый 20.06.2013, 04:05   #7
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию

Благодарю всех за участие. Думаю, что кое-что для себя прояснил.
220Volt вне форума Ответить с цитированием
Старый 25.06.2013, 07:19   #8
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию

Вопросы выравнивания полей (расположение заполнителей) регламентировано стандартом?
Т.е. как будет выровнена структура S:
Код:
struct S   // Наша запись
{
   Int i;
   short s;
};

// Запись компилятором
struct S
{
   Int i;
   char fill[2];
   short s;
};

struct S
{
   Int i;
   short s;
   char fill[2];
};

struct S
{
   Int i;
   char fill_1;
   short s;
   char fill_1;
};
В g++ и MSVC такой код выдал 0:
Код:
struct S
{
   int f;
   char d;
};

int main()
{
    S v;
    cout<<( int(&v.f)-int(&v.f) );
}
Но на всякий случай.
220Volt вне форума Ответить с цитированием
Старый 25.06.2013, 07:39   #9
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию

Код:
struct S 
{
   Int i;
   char fill_1;
   short s;
   char fill_1;
};
Это я зря написал, ведь адрес s должен быть кратен ее размеру, следовательно вариант неверен
220Volt вне форума Ответить с цитированием
Старый 25.06.2013, 11:38   #10
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Код:
#include <iostream>
 
using namespace std;
 
struct S
{
   int i;
   short s;
};
 
int
main()
{
    S a;
    cout << int(&a.s) - int(&a) << endl << sizeof(a);
}
s на 4 байта сдвинута от начала.
Структура размера 8.
Код:
struct S
{
   Int i;
   short s;
   char fill[2];
};
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
выравнивание skauzer_blr Помощь студентам 0 05.06.2012 22:07
Выравнивание в Label usmeshnik Компоненты Delphi 4 03.03.2011 20:10
выравнивание street-walker Общие вопросы Delphi 0 16.03.2010 22:10
выравнивание wolf950 HTML и CSS 2 17.03.2009 10:05