Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Размещение объекта в памяти


Автор: ForceKeeper 16.1.2011, 02:41
Есть класс, в который я не могу залезть ручками, и мне нужно располагать объекты данного класса по адресам, которые определю я сам. Можно ли еще это как-то сделать без глобальной перегрузки new?

Автор: azesmcar 16.1.2011, 07:41
Да.
Код

new (ptr) X();

http://en.wikipedia.org/wiki/Placement_syntax

Автор: ForceKeeper 16.1.2011, 19:47
Ага, тогда тут по теме еще такой вопрос появился:

Вообще я попробую написать собственный аллокатор и соответственно мне нужно проводить выравнивание. В туторе, который я смотрел, там адреса сразу были записаны в 32-битные ансайты и соответственно оперировали с ними (в частности использовали побитовое *и* для выделения окончания адреса). Так вот я хотел свои void* при помощи intptr_t reinterpret_cast перекинуть в инты, осуществить выравнивание и затем обратно кинуть исправленный адрес в указатель. Но потом мне сказали, что на 64-битных форточках адрес может быть восьмибайтовым, в то время как инт четырехбайтовый. Это так? Если да, то как бороться с этой проблемой?

Автор: azesmcar 17.1.2011, 09:27
Код

template <typename T>
T* align(T* ptr, std::size_t align)
{
    T* nptr = static_cast<T*>(0);
    return nptr + (((ptr - nptr) + align - 1) & ~(align - 1));
}

Вот так должно быть переносимо. По сути ptrdiff_t обязан быть достаточного размера, чтобы хранить разницу двух указателей, нигде не говорится, что второй указатель не может быть null, т.е. ptrdiff_t (результат вычитания двух указателей) должен быть минимум того же размера, что и сам указатель. Я так думаю © smile 

Автор: xvr 17.1.2011, 15:13
Цитата(azesmcar @  17.1.2011,  09:27 Найти цитируемый пост)
Вот так должно быть переносимо
Переносимо, но неправильно  smile Разница между указателями на T (T*) будет выражена в sizeof(T), а не в байтах  smile Так что надо приводить указатель к целочисленному типу, и с ним уже играться. И приводить надо к size_t


Автор: azesmcar 17.1.2011, 15:15
Цитата(xvr @  17.1.2011,  15:13 Найти цитируемый пост)
Переносимо, но неправильно   Разница между указателями на T (T*) будет выражена в sizeof(T),

а, ну да smile сперва написал на char, потом заменил на T*..
Код

void* align(void* ptr, std::size_t align)
{
    char* nptr = static_cast<char*>(0);
    return nptr + (((static_cast<char*>(ptr) - nptr) + align - 1) & ~(align - 1));
}

пусть будет вот так

Автор: ForceKeeper 17.1.2011, 15:20
Эм, только что проверил для адреса 0x50341233 с 16-байтовым выравниванием, результат был 0x50341240. То есть как и положено. Для 8-байтового пойнтера 0x0000000050341233 аналогично 0x0000000050341240

Автор: azesmcar 17.1.2011, 15:24
Цитата(xvr @  17.1.2011,  15:13 Найти цитируемый пост)
И приводить надо к size_t

а есть ли гарантия, что size_t того же размера, что и void*?

Автор: xvr 17.1.2011, 15:57
Цитата(azesmcar @ 17.1.2011,  15:24)
Цитата(xvr @  17.1.2011,  15:13 Найти цитируемый пост)
И приводить надо к size_t

а есть ли гарантия, что size_t того же размера, что и void*?

Практически - да. Т.к. size_t описывает тип, в который должен влезть размер любого объекта в памяти, т.е. размерностью не менее размерности адресного пространства. (Однако никто не может запретить поинтеру быть больше, чем размерность адресного пространства - например не использовать часть битов представления поинтеров).
Надо бы в стандарте глянуть  smile 

Автор: azesmcar 17.1.2011, 16:00
Цитата(xvr @  17.1.2011,  15:57 Найти цитируемый пост)
Надо бы в стандарте глянуть    

я вроде как не нашел, потому через ptrdiff_t сделал.
может плохо искал, если что найдешь дай знать.

Автор: baldina 17.1.2011, 17:54
строго говоря для безопасного и переносимого хранения указателей следует использовать uintptr_t
хотя в большинстве практических случаев sizeof(size_t)==sizeof(uintptr_t)

Автор: azesmcar 18.1.2011, 10:20
Цитата(baldina @  17.1.2011,  17:54 Найти цитируемый пост)
строго говоря для безопасного и переносимого хранения указателей следует использовать uintptr_t

но это в новом стандарте, а пока...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)