Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 25.07.05 23:48
Оценка: 1 (1)
Понимаю, что вопрос уже навяз в зубах, но поиск ничего конкретного не дал.
Вот полное описание объекта:
struct point
{
   int x,y;
   point() {}
   point(int x_, int y_) : x(x_), y(y_) {}
};


Вопрос первый — является ли данный объект POD-типом? Согласно стандарту — не является, поскольку имеет явные конструкторы.
Вопрос второй — допустимо ли копировать данный объект целиком при помощи memcpy (хранить его в специализированном контейнере для POD-типов)?
Вопрос третий. Если не допустимо, то каково обоснование этому? Класс не содержит и не может содержать никаких неявных данных, типа VMT. Так же не имеет права иметь явный деструктор. Он не может наследоваться от чего-либо и не может иметь производных классов. Имеется так же запрет на какие-либо исключения. В нем даже нет никаких указателей — только базовые типы (это все — начальные условия). И только лишь от наличия одного конструктора, имеющего чисто утилитарное назначение (как синтаксический сахар) объект нельзя копировать при помощи memcpy? Это же маразм!
Вопрос четвертый. Где-либо, когда-либо, кто-либо сталкивался с реальными проблемами на практике, при "безбашенном" копировании подобных объектов при помощи memcpy (или memmove)? По-моему, таких проблем никогда не было и не будет.
Вопрос пятый — как следствие из четвертого. Возможна ли в принципе такая ситуация (при оговоренных выше ограничениях), что добавление простого конструктора изменит sizeof объекта?

То есть, я не вижу ни малейшего rationale подобных запретов. Да, как только в конструкторе аллокируется какая-либо память (а в деструкторе освобождается), объект сразу перестает быть POD-типом. Это совершенно логично и не вызывает ни малейших возражений. Но просто запрет каких бы то ни было конструкторов — это уже какой-то параноидальный объектно-ориентированный шовинизм
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re: Снова конструкторы и POD-типы
От: Павел Кузнецов  
Дата: 26.07.05 00:58
Оценка: 3 (1)
McSeem2,

>
> struct point
> {
>    int x,y;
>    point() {}
>    point(int x_, int y_) : x(x_), y(y_) {}
> };
>

> Вопрос первый — является ли данный объект POD-типом? Согласно стандарту — не является, поскольку имеет явные конструкторы.

Да, не является.

> Вопрос второй — допустимо ли копировать данный объект целиком при помощи memcpy (хранить его в специализированном контейнере для POD-типов)?


С точки зрения стандарта — нет.

> Вопрос третий. Если не допустимо, то каково обоснование этому?


Как это ни забавно, экономическое: ресурсы комитета очень ограничены. Если бы стандарт говорил, что такой класс можно копировать с помощью memcpy, то в стандарте нужно было бы указать: 1) что такое "такой класс"; 2) что именно произойдет, если его скопировать при помощи memcpy. Уже даже ответы на эти вопросы не так тривиальны, как может показаться на первый взгляд. Дальше — хуже. Фактически, нужно вводить особую разновидность объектов для поддержания memcpy для них. Когда начинается и заканчивается lifetime такого объекта? Определение POD не подходит, определение "обычных" объектов с нетривиальным конструктором — тоже. И т.п.

Если хочешь поддержки стандартом, пользуйся чуть-чуть другой стратегией создания объектов:
struct point
{
    int x,y;
};

inline
point make_point(int x_, int y_) { point pt = { x_, y_}; return pt; }

И стандарт будет счастлив, и твоя совесть спокойна

> <...> только лишь от наличия одного конструктора, имеющего чисто утилитарное назначение (как синтаксический сахар) объект нельзя копировать при помощи memcpy? Это же маразм!


Проблема в выработке точной спецификации, что такое "конструктор, имеющий чисто утилитарное назначение". А учитывая наличие простого workaround, игра просто-напросто не стоит свеч.

> Вопрос четвертый. Где-либо, когда-либо, кто-либо сталкивался с реальными проблемами на практике, при "безбашенном" копировании подобных объектов при помощи memcpy (или memmove)? По-моему, таких проблем никогда не было и не будет.


Они могут появиться, если, скажем, в отладочной версии, компилятор добавит проверки, что объект был сконструирован, прежде чем разрешать им пользоваться, если класс имеет нетривиальный конструктор.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: Снова конструкторы и POD-типы
От: Павел Кузнецов  
Дата: 26.07.05 01:17
Оценка:
P.S.

> Как это ни забавно, экономическое: ресурсы комитета очень ограничены. <...>


На самом деле, все еще проще. Если ты считаешь, что эта функциональность нужна, ты можешь выработать formal proposal, включая точные изменения в тексте стандарта, и комитетчики обязаны будут его рассмотреть. Вопрос: тебе оно настолько нужно?
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 01:25
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>struct point
ПК>{
ПК>    int x,y;
ПК>};

ПК>inline
ПК>point make_point(int x_, int y_) { point pt = { x_, y_}; return pt; }

ПК>И стандарт будет счастлив, и твоя совесть спокойна

Очень не хочется возвращать значение... Это у меня такая фобия

А так можно?
struct point
{
    int x,y;
    static point make(int x_, int y_) { point pt = { x_, y_}; return pt; }
};



А так?
struct point
{
    int x,y;
    point clone(int x_, int y_) { point pt; memcpy(pt, this, sizeof(pt)); return pt; }
};


Но вообще-то говоря, мне хочется иметь некий тип, свободно копируемый при помощи memcpy и имеющий некую инициализацию по умолчанию плюс возможность присвоить один-два значения при создании. Все! Никаких аллокаций, ни деструкторов, ни чего прочего — чисто сишная структура с инициализацией.
IMO, это тот самый случай, когда спецификация сама себе наступила на хвост...

ПК>Они могут появиться, если, скажем, в отладочной версии, компилятор добавит проверки, что объект был сконструирован, прежде чем разрешать им пользоваться, если класс имеет нетривиальный конструктор.


Хм. А где-нибудь такой отладчик в реальности существует? В общем, я пока что рискну считать, что при данных условиях копировать можно. Есть в этом некий риск, но IMO, он на практике стремится к нулю.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: Снова конструкторы и POD-типы
От: Шахтер Интернет  
Дата: 26.07.05 01:39
Оценка:
Здравствуйте, McSeem2, Вы писали:

Можно так делать

struct Point
 {
  int x,y;
 };
 
struct SetPoint : Point
 {
  SetPoint() : Point() {}
  
  SetPoint(int x_,int y_)
   {
    x=x_;
    y=y_;
   }
 };

/* main() */ 

int main()
 {
  Point p=SetPoint();
  Point q=SetPoint(1,2);
 
  return 0;
 }
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Снова конструкторы и POD-типы
От: Шахтер Интернет  
Дата: 26.07.05 01:45
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Как это ни забавно, экономическое: ресурсы комитета очень ограничены.


А эти экономические причины не помешали включить STL в стандарт языка?
Или это тоже делалось по экономическим причинам (только другого сорта)?

Мне, например, непонятно, почему ряд простейших вопросов (типа itoa), комитет урегулировать не может и эти мелочи годами отравляют жизнь.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 01:48
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>На самом деле, все еще проще. Если ты считаешь, что эта функциональность нужна, ты можешь выработать formal proposal, включая точные изменения в тексте стандарта, и комитетчики обязаны будут его рассмотреть. Вопрос: тебе оно настолько нужно?


В данном случае, весь formal proposal заключается в том, чтобы не доводить до абсурда. И просто исключить наличие конструктора из формальных признаков не-POD типа. В самом деле — в структуре может быть некий указатель, при этом она остается POD. Наличие простых (невиртуальных) функций-членов допустимо в POD (или я ошибаюсь?). Но я могу явно написать my_ctor() и my_dtor(), которые буду вызывать вручную. И если они будут аллокировать и освобождать память, то структура сразу перестает быть POD, хотя формально она так ей и остается. С этой точки зрения, конструктор ничем не отличается от функции-члена и не может являться никаким формальным признаком. А вот деструктор — уже может. Ибо в POD-структуре по определению никогда ничего не требуется уничтожать. А вот инициализировать при создании — требуется.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[4]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 01:54
Оценка:
Здравствуйте, Шахтер, Вы писали:
Ш>Можно так делать
Ш>[ccode]
Ш>struct Point
Ш> {
Ш> int x,y;
Ш> };

Ш>struct SetPoint : Point

Ш> {
Ш> SetPoint() : Point() {}

Ш> SetPoint(int x_,int y_)

Ш> {
Ш> x=x_;
Ш> y=y_;
Ш> }
Ш> };

Это тоже не фонтан из за необходимости использовать явные присвоения заместо списка инициализации. Кстати, явный оператор присвоения в POD-типах разрешен?
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: Снова конструкторы и POD-типы
От: Павел Кузнецов  
Дата: 26.07.05 02:24
Оценка:
Шахтер,

ПК>> Как это ни забавно, экономическое: ресурсы комитета очень ограничены.


Ш> А эти экономические причины не помешали включить STL в стандарт языка?


Как видишь, не помешали

Ш> Мне, например, непонятно, почему ряд простейших вопросов (типа itoa),

Ш> комитет урегулировать не может и эти мелочи годами отравляют жизнь.

Дык, все просто: volunteer. Только данная функция относится к стандарту C,
соответственно, нужно участвовать в работе комитета по стандартизации C.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: Снова конструкторы и POD-типы
От: Павел Кузнецов  
Дата: 26.07.05 02:42
Оценка: 1 (1)
McSeem2,

M> В данном случае, весь formal proposal заключается в том, чтобы не

M> доводить до абсурда. И просто исключить наличие конструктора из
M> формальных признаков не-POD типа.

Так работать не будет. Конструктор по умолчанию включен в определение агрегатных
типов. POD-типы это свойство "наследуют" от агрегатных. Если к агрегатным типам
причислить типы, имеющие конструкторы по умолчанию, то "поплывут" многие места в
стандарте. Если изменить определение POD-типов, тоже много чего "поплывет". Нужно
очень аккуратно проходиться по тексту всего стандарта.

В общем, хочешь что-то в этом изменить -- volunteer.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: Снова конструкторы и POD-типы
От: Павел Кузнецов  
Дата: 26.07.05 02:56
Оценка:
McSeem2,

M> Но вообще-то говоря, мне хочется иметь некий тип, свободно копируемый

M> при помощи memcpy

А зачем? Чем std::copy не устраивает?

M> чисто сишная структура с инициализацией


Тут два противоречивых положения: сишные структуры не имеют "автоматической"
инициализации по определению.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Снова конструкторы и POD-типы
От: Павел Кузнецов  
Дата: 26.07.05 03:03
Оценка:
McSeem2,

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


См. тему с участием комитетчиков, там они прямым текстом дают rationale:
http://groups-beta.google.com/group/comp.std.c++/browse_frm/thread/56961680e16b8bdf
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 04:02
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>А зачем? Чем std::copy не устраивает?


А она умеет яростно копировать большие массивы, так же эффективно, как и memcpy?
Что-то мне подсказывает, что во многих случаях будут мощные накладные расходы, особенно, если структура содержит множество других структур. Да, в определенных частных случаях скорость та же, но полагаться на это нельзя — в других случаях (другая платформа, другой компилятор) — разница в разы. А мне хочется именно гарантии и стабильности.

M>> чисто сишная структура с инициализацией


ПК>Тут два противоречивых положения: сишные структуры не имеют "автоматической"

ПК>инициализации по определению.

Ну хорошо, пусть они не будут POD. Тогда можно ввести понятие "bitwise copyable". То есть, такой объект, который 100%-тно сохраняет валидность при побитовом копировании. Тем более, что на практике, так оно и есть для объектов, описанных мной в начальном сообщении. Надо это всего лишь узаконить.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[2]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 04:12
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>См. тему с участием комитетчиков, там они прямым текстом дают rationale:

ПК>http://groups-beta.google.com/group/comp.std.c++/browse_frm/thread/56961680e16b8bdf

Это все понятно, но это никак не объясняет, почему подобные объекты (POD с конструктором и принципиально прзиционно независимые) нельзя копировать напрямую.
Еще раз. Пусть они не будут POD, и их нельзя инициализировать через "{}". Но пусть они будут bitwise copyable, причем официально. Тем более, что на практике они так copyable.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[5]: Снова конструкторы и POD-типы
От: CrystaX Россия https://crystax.me/
Дата: 26.07.05 05:17
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>А она умеет яростно копировать большие массивы, так же эффективно, как и memcpy?

MS>Что-то мне подсказывает, что во многих случаях будут мощные накладные расходы, особенно, если структура содержит множество других структур. Да, в определенных частных случаях скорость та же, но полагаться на это нельзя — в других случаях (другая платформа, другой компилятор) — разница в разы. А мне хочется именно гарантии и стабильности.

Если речь идет о STLport — то умеет. Там есть copy helper, принимающий доп. параметр. В стандартной copy вызывается copy helper и передается ему кроме прочих параметров is_pod_type. Выбор происходит, естественно, в compile-time.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[6]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 05:29
Оценка:
Здравствуйте, CrystaX, Вы писали:

CX>Если речь идет о STLport — то умеет. Там есть copy helper, принимающий доп. параметр. В стандартной copy вызывается copy helper и передается ему кроме прочих параметров is_pod_type. Выбор происходит, естественно, в compile-time.


Спасибо, но на это не подходит. Я не имею права полагаться на какую-либо конкретную имплементацию. Можно полагаться лишь на просто стандартизованную STL, а какая конкретно будет использоваться — мне не ведомо. А memcpy есть везде.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[5]: Снова конструкторы и POD-типы
От: Bell Россия  
Дата: 26.07.05 06:54
Оценка: +1
Здравствуйте, McSeem2, Вы писали:

MS>Здравствуйте, Павел Кузнецов, Вы писали:


ПК>>А зачем? Чем std::copy не устраивает?


MS>А она умеет яростно копировать большие массивы, так же эффективно, как и memcpy?

MS>Что-то мне подсказывает, что во многих случаях будут мощные накладные расходы, особенно, если структура содержит множество других структур. Да, в определенных частных случаях скорость та же, но полагаться на это нельзя — в других случаях (другая платформа, другой компилятор) — разница в разы. А мне хочется именно гарантии и стабильности.

Совсем не факт, что использование memcpy решит все твои проблемы.
Посмотри например здесь
Автор: Анатолий Широков
Дата: 05.06.03
и здесь
Любите книгу — источник знаний (с) М.Горький
Re[5]: Снова конструкторы и POD-типы
От: Анатолий Широков СССР  
Дата: 26.07.05 07:33
Оценка:
Для таких примитивных типов можно использовать и подобного рода инициализацию:

struct point
{
   int x, y;
};

...
point pt = {0, 0};


И наглядно и эффективно.
Re[5]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 26.07.05 10:39
Оценка: 11 (2)
McSeem2 wrote:

> ПК>А зачем? Чем std::copy не устраивает?

> А она умеет яростно копировать большие массивы, так же эффективно, как
> и memcpy?

Делай спецификацию для нужных типов, чтобы она копировала с помощью memcpy.

Вот кусок из моей библиотеки контейнеров (будет время — напишу о ней
подробнее):
///////////////////////////////////////////////////////////////////////////////////////
////// Move traits
///////////////////////////////////////////////////////////////////////////////////////
//General fall-back implementation of move using copy-constructors.
template<class T> struct safe_move_traits
{
    static void destroy_range(T* _first, T* _last)
    {
        for (T* f=_first; f!=_last; f++)
            f->~T();
    }

    static void move(T* _first, T* _last, void *_dest)
    {
        copy(_first,_last,_dest);
        destroy_range(_first,_last);
    }

    static void copy(const T* _first, const T* _last, void *_dest)
    {
        T* tdest = static_cast<T*>(_dest);
        std::uninitialized_copy(_first,_last,_dest);
    }
};

//Fast memmove-backed mover
template<class T> struct memmove_traits
{
    enum{bitwise_moveable=1};

    static void destroy_range(T* _first, T* _last)
    {
        for (T* f=_first; f!=_last; f++)
            f->~T();
    }

    static void move(T* _first, T* _last, void *_dest)
    {
        copy(_first,_last,_dest);
        destroy_range(_first,_last);
    }

    static void copy(const T* _first, const T* _last, void *_dest)
    {
        memmove(_dest,_first,(_last-_first)*sizeof(T));
    }
};

///////////////////////////////////////////////////////////////////////////////////////
////// Automatic moveфв selectors
///////////////////////////////////////////////////////////////////////////////////////

template <class T> struct fast_move_flag
{
    enum{can_move=0};
};

#define ENABLE_BITWISE_MOVE(clazz) template<> struct 
fast_move_flag<clazz>{enum{can_move=1};};

//All non-classes or types with fast_move_flag!=0 can be moved using 
memmove.
template <class T> struct move_traits:
    public boost::mpl::if_c<boost::is_class<T>::value == 0 || 
fast_move_flag<T>::can_move,
        memmove_traits<T>, safe_move_traits<T>
    >::type
{
};

В этом коде можно многое улучшить, но идея должна быть понятна.

Более того, если у тебя есть свой класс, который может быть "почти
скопирован" с помощью memcpy (допустим, требуются небольшие изменения) —
делаешь спецификацию шаблона move_traits и наслаждаешься.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[6]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 14:14
Оценка:
Здравствуйте, Bell, Вы писали:

B>Совсем не факт, что использование memcpy решит все твои проблемы.

B>Посмотри например здесь
Автор: Анатолий Широков
Дата: 05.06.03
и здесь


Спасибо за ссылки. Во-первых, насчет производительности. Я знаю, что можно копировать быстрее, чем memcpy. Даже простой цикл оптимизатор может векторизовать и задействовать 64-битовые операции MMX. Но здесь нет никаких гарантий. Пусть (даже в большинстве случаев) memcpy работает медленнее на несколько процентов. Но она обладает очень важным свойством — предсказуемостью производительности.

Хорошо, раскрываю карты. Дело даже не в производительности. Как мне при поможи std::copy() корректно "вытащить" данные из памяти, находящиеся по невыровненному адресу? По-моему никак. На всяких SGI сразу получаем автобусную ошибку. Для чего это надо? А вот для чего. У нас есть линейный упакованный поток данных в памяти:
"char cmd; int x; int y".
Этих данных может быть многие мегабайты. Если мы представим их в виде структуры:
struct point
{
   char cmd;
   int x,y;
};

Мы неизбежно получаем полуторный перерасход по памяти из за выравнивания. Если же мы отделим cmd от x,y, то получаем упакованные и невыровненные данные. "Легализовать" невыровненные данные можно только простым побитовым копированием. Разделить на два потока в данном случае можно, но в реальности, структура этого потока значительно сложнее — что-то типа бинарного XML. И там иногда попадаются достаточно сложные структуры. Конечно же, в этих структурах могут быть и "дырки" от выравнивания, но их процент исчезающе мал, основная масса данных является упакованной. Сложные структуры всегда восстанавливаются корректно, поскольку были записаны ровно тем же путем. Получается, что C++ в чистом виде не справляется с решением подобной задачи. И только лишь из за того, что запретили побитовое копирование объектов, имеющих конструктор. Классическое решение — сделать "нормальные" классы с методами "serialize/deserialize". Но во-первых, от этого появляется много мусорного кода (внутри мне все равно придется использовать побайтное копирование), а во-вторых, это не всегда возможно. Я все-таки склонен взять на себя риск нарушить этот запрет.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[7]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 26.07.05 14:20
Оценка:
McSeem2 wrote:

> Хорошо, раскрываю карты. Дело даже не в производительности. Как мне

> при поможи std::copy() корректно "вытащить" данные из памяти,
> находящиеся по невыровненному адресу? По-моему никак.

Данный конкретный случай в std::copy как раз работать будет.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[6]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 14:30
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>//Fast memmove-backed mover
C>template<class T> struct memmove_traits
C>{
C>    enum{bitwise_moveable=1};

C>    static void destroy_range(T* _first, T* _last)
C>    {
C>        for (T* f=_first; f!=_last; f++)
            f->~T();
C>    }
C>    . . .



C>В этом коде можно многое улучшить, но идея должна быть понятна.


Идея понятна, спасибо. Но чисто в качестве придирки — это уже полное безобразие (я не хочу наглеть до такой степени): Если объект является bitwise_moveable, то он по определению не может иметь нетривиальный деструктор (который что-то там реально уничтожает). Если же деструктор действительно что-то делает, сразу ставим жирный крест на побитовом копировании. Такое ограничение представляется мне вполне разумным, ибо опасно.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[6]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 14:34
Оценка: :))) :))
Здравствуйте, Анатолий Широков, Вы писали:
АШ>struct point
АШ>{
АШ>   int x, y;
АШ>};

АШ>...
АШ>point pt = {0, 0};
АШ>

АШ>И наглядно и эффективно.

Хочу конструктор! Ыыыыыыаааааа!!! (размазывая слезы и сопли)
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[7]: Снова конструкторы и POD-типы
От: Bell Россия  
Дата: 26.07.05 14:37
Оценка:
Здравствуйте, McSeem2, Вы писали:

Ну что тут сказать В принципе, я с тобой согласен.
Ну а в желании "взять на себя риск нарушить этот запрет" ты далеко не одинок. По крайней мере я встречал это нарушение не так уж и редко
Любите книгу — источник знаний (с) М.Горький
Re[8]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 14:40
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Данный конкретный случай в std::copy как раз работать будет.


        // TEMPLATE FUNCTION copy
template<class _II, class _OI> inline
    _OI copy(_II _F, _II _L, _OI _X)
    {for (; _F != _L; ++_X, ++_F)
        *_X = *_F;
    return (_X); }


Как? Здесь будет мгновенная автобусная ошибка. Можно, конечно написать специализации для всех типов объектов, но это опять же много лишней работы.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[7]: Снова конструкторы и POD-типы
От: Анатолий Широков СССР  
Дата: 26.07.05 15:02
Оценка: 10 (1)
MS>Хочу конструктор! Ыыыыыыаааааа!!! (размазывая слезы и сопли)

Если хочется именно конструирование, то отдай его на откуп врапперам. Например:


...
template<typename T, typename P1, typename P2>
T pod_initializer(P1 p1, P2 p2)
{
     T tmp = {p1, p2};
     return tmp; 
}

struct point 
{
    int x, y;
};

class cpoint
{
    point pt;
public:
    cpoint(int x, int y) : pt(pod_initializer<point>(x, y))
    {
    }
    operator point& ()
    {
        return pt;
    }
    operator point const & () const
    {
        return pt;
    }
    point* operator &()
    {
        return &pt;
    }
    point const * operator &() const
    {
        return &pt;
    }
};

void foo(point const &pt)
{
    std::cout << pt.x << ", " << pt.y << std::endl;
}

void foo(point const *ptr)
{
    std::cout << ptr->x << ", " << ptr->y << std::endl;
}

int main()
{
    std::cout << sizeof(point) << sizeof(cpoint);
    cpoint pt1(100, 200);
    cpoint pt2(300, 200);
    foo(&pt1);
    foo(&pt2);
}
Re[7]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 26.07.05 15:13
Оценка: +1
McSeem2 wrote:

> C>В этом коде можно многое улучшить, но идея должна быть понятна.

> Идея понятна, спасибо. Но чисто в качестве придирки — это уже полное
> безобразие (я не хочу наглеть до такой степени): Если объект является
> bitwise_moveable, то он по определению не может иметь нетривиальный
> деструктор (который что-то там реально уничтожает).

Не обязательно, у меня используются бит-копируемые объекты, в которых в
деструкторе делаются assert'ы и некоторые другие проверки. Так что пусть
живет.

> Если же деструктор действительно что-то делает, сразу ставим жирный

> крест на побитовом копировании. Такое ограничение представляется мне
> вполне разумным, ибо опасно.

У меня по умолчанию побитовое копирование будет работать только для
простых типов. Для более сложных нужно ставить флажок
ENABLE_BITWISE_MOVEABLE — если его явно поставить, то уж сам виноват....

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[9]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 26.07.05 17:25
Оценка:
McSeem2 wrote:

> C>Данный конкретный случай в std::copy как раз работать будет.

>
> // TEMPLATE FUNCTION copy
>template<class _II, class _OI> inline
> _OI copy(_II _F, _II _L, _OI _X)
> {for (; _F != _L; ++_X, ++_F)
> *_X = *_F;
> return (_X); }
>
> Как? Здесь будет мгновенная автобусная ошибка.

Компилятор обнаружит, что размер структуры не позволяет срабатывать
выравниванию, и сгенерирует byte-by-byte копирование. А байты везде
читаются без выравнивания.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[10]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 18:08
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Компилятор обнаружит, что размер структуры не позволяет срабатывать

C>выравниванию, и сгенерирует byte-by-byte копирование. А байты везде
C>читаются без выравнивания.

Не верю!
    struct point { int x,y; };
    char array[100];
    point p[4];
    std::copy((point*)(array+1), (point*)(array+1+sizeof(p)), p);


И что, на SGI не возникнет автобусной ошибки? Я ведь проверю! И очень скоро проверю!
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[11]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 19:34
Оценка:
#include <algorithm>

struct point { int x,y; };

void main()
{
    char array[100];
    point p[4];
    std::copy((point*)(array+1), (point*)(array+1+sizeof(p)), p);
}


rndusexwally:~>CC buserror.cpp
cc-3563 CC: WARNING File = buserror.cpp, Line = 5
  return type of function "main" must be "int"

  void main()
       ^

rndusexwally:~>./a.out
Bus error (core dumped)
rndusexwally:~>


Как и ожидалось... Интересно, откуда компилятор может заранее знать, что указатель не выровнен? Это возможно только в run-time, что есть накладно весьма.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[9]: Снова конструкторы и POD-типы
От: dad  
Дата: 26.07.05 21:14
Оценка:
а что такое:

MS>Как? Здесь будет мгновенная автобусная ошибка.


?
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[10]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 26.07.05 21:32
Оценка:
Здравствуйте, dad, Вы писали:


dad>а что такое:

MS>>Как? Здесь будет мгновенная автобусная ошибка.

Bus Error (core dumped). Обращение по невыровненному адресу, например:
char a[5] = {0}; 
int i = *(int*)(a + 1);

Такая операция в общем случае является криминалом. Но на Intel — работает.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[11]: Снова конструкторы и POD-типы
От: dad  
Дата: 27.07.05 04:39
Оценка:
dad>>а что такое:
MS>>>Как? Здесь будет мгновенная автобусная ошибка.

MS>Bus Error (core dumped). Обращение по невыровненному адресу, например:

MS>
MS>char a[5] = {0}; 
MS>int i = *(int*)(a + 1);
MS>

MS>Такая операция в общем случае является криминалом. Но на Intel — работает.

"автобусная" ошибка регламентируется стандартом?
Внешне криминала не видно, получаешь 4 байта [1-4]
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[12]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 27.07.05 05:01
Оценка:
Здравствуйте, dad, Вы писали:

dad>"автобусная" ошибка регламентируется стандартом?

dad>Внешне криминала не видно, получаешь 4 байта [1-4]

Это регламентируется не стандартом C++, а архитектурой процессоров. Если процессор не позволяет так копировать, а некий (абстрактный) язык позволяет, то bus error в run-time будет в любом языке. А стандарт не имеет права запрещать подобный криминал (да и не может по жизни). То есть, это все — на совести программиста.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[13]: Снова конструкторы и POD-типы
От: dad  
Дата: 27.07.05 05:21
Оценка:
dad>>"автобусная" ошибка регламентируется стандартом?
dad>>Внешне криминала не видно, получаешь 4 байта [1-4]

MS>Это регламентируется не стандартом C++, а архитектурой процессоров. Если процессор не позволяет так копировать, а некий (абстрактный) язык позволяет, то bus error в run-time будет в любом языке. А стандарт не имеет права запрещать подобный криминал (да и не может по жизни). То есть, это все — на совести программиста.


А на какой платформе такое у тебя? С чем это связано чисто технически.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[12]: Снова конструкторы и POD-типы
От: Павел Кузнецов  
Дата: 27.07.05 06:30
Оценка:
dad,

MS>> Bus Error (core dumped). Обращение по невыровненному адресу, например:

MS>>
 MS>> char a[5] = {0};
 MS>> int i = *(int*)(a + 1);
 MS>>

MS>> Такая операция в общем случае является криминалом. Но на Intel -
MS>> работает.

d> "автобусная" ошибка регламентируется стандартом?


Да. Ищи alignment requirements.

d> Внешне криминала не видно, получаешь 4 байта [1-4]


Данные не выравнены надлежащим для этого типа образом.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[14]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 27.07.05 06:33
Оценка:
Здравствуйте, dad, Вы писали:

dad>А на какой платформе такое у тебя? С чем это связано чисто технически.


На SGI, на Sun Ultra Sparc, на HP, на DEC Alpha и многих других. Ну не культурно это обращаться к памяти как к int, если адрес не выровнен на int. На Intel, кстати тоже. Это хоть и работает технически, но значительно медленнее, чем в случае выровненных данных. Именно поэтому в структурах появляюся "дыры" от выравнивания. И sizeof(struct) != sum(sizeof(data_members)) в общем случае.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[15]: Снова конструкторы и POD-типы
От: MaximE Великобритания  
Дата: 27.07.05 07:16
Оценка:
McSeem2 wrote:

> На SGI, на Sun Ultra Sparc, на HP, на DEC Alpha и многих других. Ну не культурно это обращаться к памяти как к int, если адрес не выровнен на int. На Intel, кстати тоже. Это хоть и работает технически, но значительно медленнее, чем в случае выровненных данных.


Я читал, что когда данные в кэш линейке, выранивание на скорость доступа на ia32 не оказывает никакого влияния. Сам не проверял.

> Именно поэтому в структурах появляюся "дыры" от выравнивания. И sizeof(struct) != sum(sizeof(data_members)) в общем случае.


В-общем случае размер структуры кратен ее выравниванию. Это связано с тем, что в массивах между элементами не может быть "дыр", поэтому если размер структуры не был бы кратен выравниванию, массив из этих структур создать не было бы возможно.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[16]: Снова конструкторы и POD-типы
От: _Winnie Россия C++.freerun
Дата: 27.07.05 08:38
Оценка:
Я и сложные типы типа std::vector, std::string двигаю по памяти при помощи memcpy... а это совсем не POD-типы. Говорят, возможно в будущем С++ стандарте будет какая-то специальная move-семантика. Но зачем усложнять язык, если это и сейчас возможно при помощи memcpy.
Правильно работающая программа — просто частный случай Undefined Behavior
Re[11]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 13:37
Оценка:
McSeem2 wrote:

> Не верю!

>
> struct point { int x,y; };
> char array[100];
> point p[4];
> std::copy((point*)(array+1), (point*)(array+1+sizeof(p)), p);
>
> И что, на SGI не возникнет автобусной ошибки? Я ведь проверю! И очень
> скоро проверю!

Так вот будет:

    struct point { int x,y; };
    char *array=(char*)malloc(100)
    point p[4];
    std::copy(&p[0], &p[0]+4, array);


--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[10]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 13:40
Оценка:
dad wrote:

> MS>Как? Здесь будет *мгновенная автобусная ошибка*.

> ?

Bus error (passangers dumped)

На нормальных системах (SPARCах, I64 и т.п.) переменная должна быть
выравнена по своему размеру. То есть 8 байтный double должен быть
выравнен по границе 8 байт, 4-байтный int по границе 4 байт и т.п.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[12]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 13:41
Оценка:
dad wrote:

> MS>Такая операция в общем случае является криминалом. Но на Intel —

> работает.
> "автобусная" ошибка регламентируется стандартом?

Да. В Стандарте есть пункты о выравнивании переменных, где упоминается о
UB в случаях неправильного выравнивания.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[17]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 13:50
Оценка:
_Winnie wrote:

> Я и сложные типы типа std::vector, std::string *двигаю* по памяти при

> помощи memcpy... а это совсем не POD-типы.

Тут ведь как, по Стандарту такое делать нельзя, но на практике обычно
работает

Специально для поддержки быстрого move'а контейнеров я написал свою
STL-совместимую библиотеку. Например, возврат вектора из метода у меня
выглядит так:
typedef bcn::vector_builder<Obj> obj_vector_builder;
typedef bcn::fast_vector<Obj> obj_vector;

obj_vector method()
{
    obj_vector_builder b;
    b.insert(10,Obj(...));
    b.push_back(Obj());
    ...

    return b.yield();
}

При этом обычно происходит всего 1 динамическая аллокация (у меня
используется _grow для увеличения размера блока).

В результате с коллекциями стало работать намного приятнее.

> Говорят, возможно в будущем С++ стандарте будет какая-то специальная

> move-семантика. Но зачем усложнять язык, если это и сейчас возможно
> при помощи memcpy.

HINT: А если в объекте есть указатели на самого себя? Или если this
используется как ключ в какой-нибудь карте?

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[16]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 27.07.05 15:37
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Я читал, что когда данные в кэш линейке, выранивание на скорость доступа на ia32 не оказывает никакого влияния. Сам не проверял.


Я тоже слышал такую версию. Но с другой стороны, я так же слышал, что для MMX/SSE операций выравнивание очень существенно влияет на производительность (причем, выравнивание на 64 или 128 бит).

>> Именно поэтому в структурах появляюся "дыры" от выравнивания. И sizeof(struct) != sum(sizeof(data_members)) в общем случае.


ME>В-общем случае размер структуры кратен ее выравниванию. Это связано с тем, что в массивах между элементами не может быть "дыр", поэтому если размер структуры не был бы кратен выравниванию, массив из этих структур создать не было бы возможно.


А что такое "выравнивание структуры"? Выравнивание по максимальному элементу данных?
struct v
{
    char a;
    int  b;
    char c;
    int  d;
    char e;
    int  f;
    char g;
    int  h;
};


Здесь все зависит от того, упорядочиват ли компилятор данные в структуре. Если нет, то размер будет таков, как если бы мы все char заменили на int. И соответственно, 4 дырки. Но вооще-то, можно отсортировать по убыванию размера, и тогда будет только небольшое пустое место в конце. Но что-то предполагать заранее нельзя.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[17]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 15:39
Оценка:
McSeem2 wrote:

> ME>Я читал, что когда данные в кэш линейке, выранивание на скорость

> доступа на ia32 не оказывает никакого влияния. Сам не проверял.
> Я тоже слышал такую версию. Но с другой стороны, я так же слышал, что
> для MMX/SSE операций выравнивание очень существенно влияет на
> производительность (причем, выравнивание на 64 или 128 бит).

Насколько я помню, SSE не умеет работать с невыровненными данными.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[17]: Снова конструкторы и POD-типы
От: Centaur Россия  
Дата: 27.07.05 18:22
Оценка: +1
MS>А что такое "выравнивание структуры"? Выравнивание по максимальному элементу данных?
MS>
MS>struct v
MS>{
MS>    char a;
MS>    int  b;
MS>    char c;
MS>    int  d;
MS>    char e;
MS>    int  f;
MS>    char g;
MS>    int  h;
MS>};
MS>


MS>Здесь все зависит от того, упорядочиват ли компилятор данные в структуре.


Переупорядочивать — в данном случае не имеет права. Ибо 9.2/1:

Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).


MS> Если нет, то размер будет таков, как если бы мы все char заменили на int. И соответственно, 4 дырки. Но вооще-то, можно отсортировать по убыванию размера, и тогда будет только небольшое пустое место в конце. Но что-то предполагать заранее нельзя.
Re[17]: Снова конструкторы и POD-типы
От: MaximE Великобритания  
Дата: 27.07.05 18:52
Оценка:
On Wed, 27 Jul 2005 19:37:35 +0400, McSeem2 <12737@users.rsdn.ru> wrote:

[]

> В-общем случае размер структуры кратен ее выравниванию. Это связано с тем, что в массивах между элементами не может быть "дыр", поэтому если размер структуры не был бы кратен выравниванию, массив из этих структур создать не было бы возможно.

>
> А что такое "выравнивание структуры"? Выравнивание по максимальному элементу данных?

Это максимальное выравнивание члена стр-ры. Выравнивание встроенных типов есть их размер.

>
> struct v
> {
>     char a;
>     int  b;
>     char c;
>     int  d;
>     char e;
>     int  f;
>     char g;
>     int  h;
> };
>

>
> Здесь все зависит от того, упорядочиват ли компилятор данные в структуре.

В POD компилятор не может переупорядочивать члены.

> Если нет, то размер будет таков, как если бы мы все char заменили на int. И соответственно, 4 дырки. Но вооще-то, можно отсортировать по убыванию размера, и тогда будет только небольшое пустое место в конце. Но что-то предполагать заранее нельзя.


Максимальное выравнивание члена в этой стр-ре — sizeof(int). Поэтому sizeof(v) % sizeof(int) == 0 и alignof(v) == alignof(int).

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[18]: Снова конструкторы и POD-типы
От: dad  
Дата: 27.07.05 19:21
Оценка:
ME>Это максимальное выравнивание члена стр-ры. Выравнивание встроенных типов есть их размер.

>>
>> struct v
>> {
>>     char a;
>>     int  b;
>>     char c;
>>     int  d;
>>     char e;
>>     int  f;
>>     char g;
>>     int  h;
>> };
>>

>>
>> Здесь все зависит от того, упорядочиват ли компилятор данные в структуре.

Ну тут понятно, но непонятно где криминал в примере МакСима вот тут:

char a[5] = {0}; 
int i = *(int*)(a + 1);


что тут по чему выровнено? мы знаем что char это 1 байт, массив всегда располагается последовательно.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[19]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 19:32
Оценка:
dad wrote:

> Ну тут понятно, но непонятно где криминал в примере МакСима вот тут:

>
>char a[5] = {0};
>int i = *(int*)(a + 1);
>
> что тут по чему выровнено? мы знаем что char это 1 байт, массив всегда
> располагается последовательно.

Предположим, что массив "a" начинается с адреса 4. Тогда a+1==5, попытка
разыменовать такой указатель на int вызовет автобусную ошибку. Правильно
надо писать примерно так (опять код из моей библиотеки ):
    //This union is used to ensure that COW storage elements will be 
properly aligned.
    template<class AllocatorT> union cow_storage_element
    {
        typedef boost::detail::atomic_count counter_type;
        typedef typename AllocatorT::value_type value_type;

        typename boost::type_with_alignment<
            (boost::alignment_of<counter_type>::value > 
boost::alignment_of<value_type>::value)
            ? boost::alignment_of<counter_type>::value
            : boost::alignment_of<value_type>::value
            >::type a;
        char counter_[sizeof(counter_type)];
        char data_[sizeof(value_type)];
    };


Теперь, например, мы можем делать так:
cow_storage_element *data=allocate(...);
new(&(data->counter_[0])) boost::detail::atomic_count(1);
...
new(&(data[1].data_[0])) value_type(...);


--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[20]: Снова конструкторы и POD-типы
От: dad  
Дата: 27.07.05 19:46
Оценка:
C>Предположим, что массив "a" начинается с адреса 4. Тогда a+1==5, попытка
C>разыменовать такой указатель на int вызовет автобусную ошибку.

Почему он вызовает ошибку то?
Мы точно знаем по адресу 5 лежит 1 байт, а 6, 7 и 8 еще три
другое дело, когда мы не значем что лежит там
как в случае с
struct {
char a[2];
int b;
};

(int*)(a + 1) -> тут понятно..
Или предполагается, что даже элементы массива типа char
могут быть выровнены на границу слова, например, без всякого нашего ведома?


C>Правильно надо писать примерно так (опять код из моей библиотеки ):


Блин я такое даже прочитать не могу
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[21]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 20:01
Оценка:
dad wrote:

> C>Предположим, что массив "a" начинается с адреса 4. Тогда a+1==5,

> попытка
> C>разыменовать такой указатель на int вызовет автобусную ошибку.
> Почему он вызовает ошибку то?

Массив "a" — это массив однобайтных символов (не требующих
выравнивания), компилятор имеет право разместить этот массив как угодно.
В том числе, может разместить по адресу, кратному 4. Следовательно
второй элемент массива (a+1) будет иметь адрес вида 4k+1.

> Мы точно знаем по адресу 5 лежит 1 байт, а 6, 7 и 8 еще три


Неважно что там лежит. Число 5 не делится на 4 (размер int'а), значит
произойдет _аппаратная_ ошибка выравнивания. Ну не может процессор с
такими данными работать.

> C>Правильно надо писать примерно так (опять код из моей библиотеки ):

> Блин я такое даже прочитать не могу

Можно записать более просто:
#ifdef _WIN32
//Non-aligned types can be safely used on win32.
template<class T> size_t alignment_of()
{
    return 1;
}
#else
//General fallback implementation.
template<class T> size_t alignment_of()
{
    return sizeof(T);
}
#endif

...

char a[5+(alignment_of(int)+1)/2]; //This array will have enough space 
for properly aligned int.
int i=*(int*)(a+a%alignment_of(int)); //Get properly aligned integer.


Либо еще можно делать так:
union
{
    char a[5];
    int i;
};



--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[20]: Снова конструкторы и POD-типы
От: MaximE Великобритания  
Дата: 27.07.05 20:03
Оценка: +1
On Wed, 27 Jul 2005 23:32:21 +0400, Cyberax <37054@users.rsdn.ru> wrote:

> dad wrote:

>
>> Ну тут понятно, но непонятно где криминал в примере МакСима вот тут:
>>
>> char a[5] = {0};
>> int i = *(int*)(a + 1);
>>
>> что тут по чему выровнено? мы знаем что char это 1 байт, массив всегда
>> располагается последовательно.
>
> Предположим, что массив "a" начинается с адреса 4. Тогда a+1==5, попытка
> разыменовать такой указатель на int вызовет автобусную ошибку. Правильно
> надо писать примерно так (опять код из моей библиотеки ):

[]

За шаблонами кода не видно. Чем не устраивает рабоче-крестьянский:

int main()
{
     size_t const align = 0x1000;
     size_t const buf_size = 8;

     char buf[buf_size + align - 1];
     char* aligned_buf = buf + align - 1 - (((uint_ptr_t)buf + align - 1) % align);

     printf("%x %x\n", buf, aligned_buf);
}


--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[21]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 28.07.05 14:09
Оценка: 4 (1)
Здравствуйте, dad, Вы писали:

dad>Почему он вызовает ошибку то?

dad>Мы точно знаем по адресу 5 лежит 1 байт, а 6, 7 и 8 еще три
dad>другое дело, когда мы не значем что лежит там
dad>как в случае с
dad>struct {
dad> char a[2];
dad> int b;
dad>};

Неважно, что и как там лежит. Важно, что адрес нечетный.
mov eax,[esi]

На многих процессорах, аналог этой команды вызовет bus error, в случае, если текущее значение esi не кратно 4.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.