Re[9]: ZeroMemory vs xxx = { 0 };
От: Дарней Россия  
Дата: 18.06.04 13:47
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>От автора оригинального сообщения я подобных заявлений не слышал. Да и какой смысл в абстрактном "низкоуровневом обнулении куска памяти", если оно не означает обнуление всех элементов структуры?


Немного отвлекся от темы. Даже не ожидал, что тут такая дискуссия развернется
Хоть я и не говорил явно про "низкоуровневое обнуление", я имел в виду именно его. Предполагать, что такой подход будет использоваться для инициализации всех структур — это просто глупо.
Единственное применение для него (по крайней мере, в моих прогах) — это обнуление структур WinAPI (для того же используют обычно и ZeroMemory). В WinAPI очень много структур с кучей полей, и все они относятся к POD, поэтому применение такого подхода вполне правомерно, ИМХО. В любом случае — это намного лучше, чем инициализация случайными значениями. Забыл про одно поле — и всё, получил прогу с непредсказуемым поведением. Ищи потом, где что неправильно.
Написать же конструкторы в данном случае невозможно по вполне понятным причинам , и по этим же причинам можно не опасаться, что там появятся поля не-POD типов.
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[12]: ZeroMemory vs xxx = { 0 };
От: Дарней Россия  
Дата: 18.06.04 13:58
Оценка:
Здравствуйте, Mr. None, Вы писали:

MN>Строго говоря функция ZeroMemory — это API-функция конкретной операционной системы и реализация компилятора тут не причём — это первое.

MN>Второе — эта операционная система предполагает, что null-pointer value — это 0 (если быть совсем точным, то это все значения указателей, расположенных в диапазоне 0x00000000 — 0x0000FFFF). Поэтому если компилятор в качестве null-pointer value выбирает скажем 0xFFFFFFFF, любой вызов API-функции, ожадающей получение указателя проинициализированного значением null-pointer values, закончиться неудачей. Следовательно либо такой компилятор будет порождать неработоспособный код, либо надо как раз пользоваться функцией ZeroMemory, а не ={0}.

Что-то я не понял логики.
В любом случае, при использовании {0} компилятор заполнит все члены структуры нулевыми значениями, а не заполнит память нулями. Иными словами, если нулевой указатель в данной реализации представлен 0xFFFFFFFF, то компилятор обязан для всех указателей в структуре поместить именно это значение. Если там находится float и у него почему-то 0 представлен не-нулевым набором битов, компилятор должен поместить туда валидное представление нулевого значения. Бестиповый "0", читаем Страуструпа.

А вот ZeroMemory или memset ничего такого гарантировать не могут.
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[13]: ZeroMemory vs xxx = { 0 };
От: achp  
Дата: 18.06.04 14:06
Оценка:
Здравствуйте, Дарней, Вы писали:

Д>А вот ZeroMemory или memset ничего такого гарантировать не могут.


Как это ничего? Они гарантируют, что нетипизированная область памяти (или массив объектов типа [un]signed] char) будет обнулена.
Re[3]: ZeroMemory vs xxx = { 0 };
От: achp  
Дата: 18.06.04 14:08
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Лечение насморка отрубанием головы: зачем использовать кучу там, где можно обойтись выделением памяти "в стеке"?


Ну, может потребоваться, если блок чересчур велик для стека.
Re[14]: ZeroMemory vs xxx = { 0 };
От: WolfHound  
Дата: 18.06.04 15:04
Оценка:
Здравствуйте, achp, Вы писали:

Д>>А вот ZeroMemory или memset ничего такого гарантировать не могут.

A>Как это ничего? Они гарантируют, что нетипизированная область памяти (или массив объектов типа [un]signed] char) будет обнулена.
Дарней говорит про ЛОГИЧЕСКОЕ обнуление, а не физическое...
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[20]: ZeroMemory vs xxx = { 0 };
От: Ivan A. Kosarev  
Дата: 18.06.04 15:25
Оценка: +1
"Павел Кузнецов" <5834@news.rsdn.ru> wrote in message news:684083@news.rsdn.ru...

> >> Я что-то ни одного не припомню, чтобы memset работал, а = { 0 } — нет.

>
> > Такое может случиться при инициализации объединений, первые члены которых имеют, например, плавающие типы.
>
> Только в таком случае возникает вопрос: а какой из двух вариантов считать работающим? Кроме того, на платформе, где 0.0 или 0.0f представляется чем-то, отличным от последовательности нулевых байтов, memset для плавающих типов все равно использовать нельзя...

Считать работающим можно любой код вообще. Часто так и делают.

Оба варианта инициализации могут не работать. Все зависит от логики работы с инициализируемым объектом.

Для абстрактных данных в Си я предлагал следующее.

/* item.h */
struct item;

struct item *allocitem(void);

/* item.c */
#include "item.h"

struct item  {
    double f;
    const void *ptr;
};

static struct item inititem(struct item *item)
{
    static const struct item initer =  {
        .0,           /* .item */
        (void*) NULL  /* .ptr */
    };
    if(item != NULL)  {
        *item = initer;
    }
    return item;
}

struct item *allocitem(void)
{
    return inititem(malloc(sizeof(struct item)));
}


Такой избавляет от массы проблем с инициализацией.

--
Иван

9899 — Полный справочник по языку Си
http://subscribe.ru/catalog/comp.soft.prog.9899
Posted via RSDN NNTP Server 1.9 beta
Re[4]: ZeroMemory vs xxx = { 0 };
От: Павел Кузнецов  
Дата: 18.06.04 15:32
Оценка:
> ПК> зачем использовать кучу там, где можно обойтись выделением памяти "в стеке"?

> Ну, может потребоваться, если блок чересчур велик для стека.


+1

Это случай, когда нельзя обойтись стеком
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[10]: ZeroMemory vs xxx = { 0 };
От: Павел Кузнецов  
Дата: 18.06.04 15:43
Оценка:
> ПК>От автора оригинального сообщения я подобных заявлений не слышал. Да и какой смысл в абстрактном "низкоуровневом обнулении куска памяти", если оно не означает обнуление всех элементов структуры?

> <...> Хоть я и не говорил явно про "низкоуровневое обнуление", я имел в виду именно его.


Ок. Если нужно побайтное обнуление — нужно использовать ZeroMemory/memset. Инициализация вида = { 0 } этого гарантировать не может. И наоборот, если нужна почленная инициализация значениями по умолчанию ("логический" 0) — нужно использовать что-нибудь из серии:
Struct s = { 0 };

Struct s = Struct();

и т.п.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[15]: ZeroMemory vs xxx = { 0 };
От: achp  
Дата: 18.06.04 15:58
Оценка:
Здравствуйте, WolfHound, Вы писали:

Д>>>А вот ZeroMemory или memset ничего такого гарантировать не могут.

A>>Как это ничего? Они гарантируют, что нетипизированная область памяти (или массив объектов типа [un]signed] char) будет обнулена.
WH>Дарней говорит про ЛОГИЧЕСКОЕ обнуление, а не физическое...

Ага, я, читая его сообщение, проглядел слово "такого".
Re[3]: ZeroMemory vs xxx = { 0 };
От: Xentrax Россия http://www.lanovets.ru
Дата: 18.06.04 19:08
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

>> Д> WNDCLASSEX wcx = { 0 };


>> а если нужно будет обнуль структурку потом,


ПК>
ПК>wcx = WNDCLASSEX();
ПК>


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

Как-то привык все обнулять почленно/конструктором/мемсетом... Обязательно посмотрю, что бывает со структурой, инициализированной {0} в таком компиляторе.
Re[11]: ZeroMemory vs xxx = { 0 };
От: Дарней Россия  
Дата: 21.06.04 06:17
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Ок. Если нужно побайтное обнуление — нужно использовать ZeroMemory/memset. Инициализация вида = { 0 } этого гарантировать не может. И наоборот, если нужна почленная инициализация значениями по умолчанию ("логический" 0) — нужно использовать что-нибудь из серии:


угу, для меня многое прояснилось.
Вроде бы такая простая вещь, а столько сложностей, оказывается
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[8]: ZeroMemory vs xxx = { 0 };
От: alexkro  
Дата: 21.06.04 06:58
Оценка: +2
Здравствуйте, Аноним, Вы писали:

>>> Все что я сказал, это то, что участок памяти отведенной под структуру будет забит нулями! Все!

ПК>>И каков смысл такого "обнуления"?
А>Смысл в том, что для многих встроенных типов семантика такого обнуления равна семантике инициализации нулем. Вместого того, чтобы писать = 0; для кучи переменных типа int проще сразу забить всю структуру нулями а затем уже подкоректировать "некоторые оставшиеся" переменные, дав им нужные значения. Все! Это я и имел в виду!

Как-то встретился мне подобный код. Большой класс, в нем много переменных встроенных типов. Очень уж неохота было кому-то инициализировать каждую переменную по отдельности. И написал он такое:
some_class::some_class() {
    ZeroMemory( this, sizeof( this ) );
}

Коротенький конструктор, три строчки, в файле из 10000 строк — не сразу заметишь. Понадобилось мне расширить этот класс. И вставил я в него переменную типа std::vector. Тут-то все и начилось. И вспомнил я того человека, кто такой конструктор написал, хорошим словом, после двух часов отладки...
Re[9]: ZeroMemory vs xxx = { 0 };
От: Шахтер Интернет  
Дата: 22.06.04 01:16
Оценка:
Здравствуйте, alexkro, Вы писали:

A>Здравствуйте, Аноним, Вы писали:


>>>> Все что я сказал, это то, что участок памяти отведенной под структуру будет забит нулями! Все!

ПК>>>И каков смысл такого "обнуления"?
А>>Смысл в том, что для многих встроенных типов семантика такого обнуления равна семантике инициализации нулем. Вместого того, чтобы писать = 0; для кучи переменных типа int проще сразу забить всю структуру нулями а затем уже подкоректировать "некоторые оставшиеся" переменные, дав им нужные значения. Все! Это я и имел в виду!

A>Как-то встретился мне подобный код. Большой класс, в нем много переменных встроенных типов. Очень уж неохота было кому-то инициализировать каждую переменную по отдельности. И написал он такое:

A>
A>some_class::some_class() {
A>    ZeroMemory( this, sizeof( this ) );
A>}
A>

A>Коротенький конструктор, три строчки, в файле из 10000 строк — не сразу заметишь. Понадобилось мне расширить этот класс. И вставил я в него переменную типа std::vector. Тут-то все и начилось. И вспомнил я того человека, кто такой конструктор написал, хорошим словом, после двух часов отладки...

Может ZeroMemory( this, sizeof( *this ) ); ?
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[10]: ZeroMemory vs xxx = { 0 };
От: alexkro  
Дата: 22.06.04 01:21
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, alexkro, Вы писали:


Ш>Может ZeroMemory( this, sizeof( *this ) ); ?


Да. Опечатка.
Re[4]: ZeroMemory vs xxx = { 0 };
От: Андрей Тарасевич Беларусь  
Дата: 22.06.04 04:20
Оценка:
Здравствуйте, Xentrax, Вы писали:


ПК>>
ПК>>wcx = WNDCLASSEX();
ПК>>


X>Тут ведь вот какая закавыка.

X>Насколько я понимаю, все эти выкрутасы используют положение стандарта о том, что для POD типов деволтный конструктор их "обнуляет".

Не "деволтный конструктор их обнуляет", а выполняется инициализация по умолчанию, которая сводится к обнулению. Конструкторы тут в большинстве случаев ни при чем. Тем более, что у некоторых POD-типов вообще нет никаких конструкторов.
Best regards,
Андрей Тарасевич
Re[9]: ZeroMemory vs xxx = { 0 };
От: Дарней Россия  
Дата: 22.06.04 04:54
Оценка:
Здравствуйте, alexkro, Вы писали:

A>Коротенький конструктор, три строчки, в файле из 10000 строк — не сразу заметишь. Понадобилось мне расширить этот класс. И вставил я в него переменную типа std::vector. Тут-то все и начилось. И вспомнил я того человека, кто такой конструктор написал, хорошим словом, после двух часов отладки...


значит, еще один аргумент против ZeroMemory
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re: ZeroMemory vs xxx = { 0 };
От: MShura  
Дата: 23.06.04 10:48
Оценка:
Здравствуйте, Дарней, Вы писали:

Д>Признаюсь честно, привык писать обнуление структур в таком стиле:


Д> WNDCLASSEX wcx = { 0 };


Д>Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак

Д>Интересно — может быть, есть какие-то аргументы против такой практики?


ZeroMemory — незаменимая вещь, если одна из структур наследует другую.

Т.е. бывает, что хочется расширить существующую структуру из POD элементов.
Можно написать копию + свои элементы, а можно наследоваться.

Если работать с C++, то "правильней", IMHO, это наследование.

После этого к расширенной таким образом структуре нельзя применять = {0}.

Во всех случаях, кроме вышеуказанного, я использую ={0}.
Re[2]: ZeroMemory vs xxx = { 0 };
От: Павел Кузнецов  
Дата: 23.06.04 14:14
Оценка:
MShura:

> ZeroMemory — незаменимая вещь, если одна из структур наследует другую. <...>

> После этого к расширенной таким образом структуре нельзя применять = {0}.

Есть три варианта кошерного "обнуления":
1) Не наследовать свою структуру, а включить в нее другую. В этом случае можно использовать = { 0 }.
2) Наследовать, но "обнулять" так:
MyStruct s = MyStruct();

3) Предоставить в унаследованной структуре конструктор, в котором и "обнулять" базовую структуру.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: ZeroMemory vs xxx = { 0 };
От: Xentrax Россия http://www.lanovets.ru
Дата: 23.06.04 17:52
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

X>>Насколько я понимаю, все эти выкрутасы используют положение стандарта о том, что для POD типов деволтный конструктор их "обнуляет".


АТ>Не "деволтный конструктор их обнуляет", а выполняется инициализация по умолчанию, которая сводится к обнулению. Конструкторы тут в большинстве случаев ни при чем.


Да, незавимо от корректности построения фраз, выяснилось, что, даже в случае компилятора, который не выполняет иницализацию по умолчанию для POD типов, ={0} "обнуляет" (ну то есть выполняет инициализацию по умочанию) для входящих в структуру полей. И отказывается компилировать, если одно из полей или сама структура имеет конструктор.


АТ>Тем более, что у некоторых POD-типов вообще нет никаких конструкторов.


А что тогда для них вызывает какой-нибудь std::vector при вызове vector::vector(size_type)?
Re[3]: ZeroMemory vs xxx = { 0 };
От: MShura  
Дата: 24.06.04 11:34
Оценка:
>> ZeroMemory — незаменимая вещь, если одна из структур наследует другую. <...>
>> После этого к расширенной таким образом структуре нельзя применять = {0}.

ПК>Есть три варианта кошерного "обнуления":


ПК>2) Наследовать, но "обнулять" так:

ПК>
ПК>MyStruct s = MyStruct();
ПК>

Не знаю что говорят об этом стандарты, но практика говорит, что ни VC6, ни VC7, ни gcc 3.2.2, ни Watcom 11 таким образом не "обнулят" структуру это точно.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.