Признаюсь честно, привык писать обнуление структур в таком стиле:
WNDCLASSEX wcx = { 0 };
Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак
Интересно — может быть, есть какие-то аргументы против такой практики?
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re: ZeroMemory vs xxx = { 0 };
От:
Аноним
Дата:
11.06.04 12:28
Оценка:
Здравствуйте, Дарней, Вы писали:
Д>Признаюсь честно, привык писать обнуление структур в таком стиле:
Д> WNDCLASSEX wcx = { 0 };
Д>Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак Д>Интересно — может быть, есть какие-то аргументы против такой практики?
Почему хак?
Здравствуйте, Дарней, Вы писали:
Д>Признаюсь честно, привык писать обнуление структур в таком стиле: Д> WNDCLASSEX wcx = { 0 }; Д>Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак Д>Интересно — может быть, есть какие-то аргументы против такой практики?
Против не скажу, но мне достаточно того, что в своих книгах Рихтер нередко
именно к такому способ и обращается.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Дарней, Вы писали:
Д>Признаюсь честно, привык писать обнуление структур в таком стиле:
Д> WNDCLASSEX wcx = { 0 };
Д>Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак Д>Интересно — может быть, есть какие-то аргументы против такой практики?
Т.е. просто напросто вставляется код, который нулями забивает участок памяти длиной размера структуры.
для вызова ZeroMemory вроде call будет, а потом примерно такой же код с начальными проверками на валидность указателей, а тут уже сразу известно что указатели валидны, т.е. получается что {0} будет немного быстрее.
K>для вызова ZeroMemory вроде call будет, а потом примерно такой же код с начальными проверками на валидность указателей, а тут уже сразу известно что указатели валидны, т.е. получается что {0} будет немного быстрее.
Вряд ли потому что ZeroMemory определен при помощи DEFINE как memset((Destination),0,(Length)),
а memset в свою очередь инлайнится компилятором.
... << Rsdn@Home 1.1.4 beta 1 >>
Re: ZeroMemory vs xxx = { 0 };
От:
Аноним
Дата:
12.06.04 01:46
Оценка:
Д>Признаюсь честно, привык писать обнуление структур в таком стиле:
Д> WNDCLASSEX wcx = { 0 };
Д>Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак Д>Интересно — может быть, есть какие-то аргументы против такой практики?
По стандарту, если хотя бы один элемент массива инициализирован, то все остальные элементы будут установлены в ноль (для встроенных типов). Для элементов структур — не знаю, но все-таки мне кажется, что запись выше должна инициализировать только первый элемент структуры, а ассемблерный код, что привели выше — по-моему это из серии "the standard is what my compiler supports!" То есть, генерируется код, который совсем не должен там быть, но это только мое ИМХО.
Лично мне такая запись не нравится по причине названной выше и очень не нравится, что Рихтер делает также (может заметили, что у него и другие ошибки есть?). Ричард Стивенс, чей уровень намного выше Рихтера никогда не позволяет себе так обнулять структуру — только через memset() и bzero() — и я также делаю как и он.
Лучше использовать ZeroMemory(), ну а если кого-то смущает, что это лишний вызов, то пусть переходят на ассемблер. Это не та часть кода где нужно считать циклы ЦПУ!
> Д> WNDCLASSEX wcx = { 0 }; > > Д>Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак > Д>Интересно — может быть, есть какие-то аргументы против такой практики?
> По стандарту, если хотя бы один элемент массива инициализирован, то все остальные элементы будут установлены в ноль (для встроенных типов). Для элементов структур — не знаю, но все-таки мне кажется, что запись выше должна инициализировать только первый элемент структуры
Стандарт не разделяет инициализацию массивов и структур, а говорит об инициализации агрегатов вообще:
8.5.1/7 If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be value-initialized (8.5). [Example:
struct S { int a; char* b; int c; };
S ss = { 1, "asdf" };
initializes ss.a with 1, ss.b with "asdf", and ss.c with the value of an expression of the form
int(), that is, 0. ]
> Лучше использовать ZeroMemory()
Отнюдь, использовать ZeroMemory() значительно хуже: не для всех типов заполнение нулями создает сколько-нибудь "осмысленное" значение. Среди них как типы, определяемые пользователем, так и некоторые встроенные (например, плавающие или указатели на члены).
Posted via RSDN NNTP Server 1.9 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: ZeroMemory vs xxx = { 0 };
От:
Аноним
Дата:
12.06.04 16:11
Оценка:
ПК>Отнюдь, использовать ZeroMemory() значительно хуже: не для всех типов заполнение нулями создает сколько-нибудь "осмысленное" значение. Среди них как типы, определяемые пользователем, так и некоторые встроенные (например, плавающие или указатели на члены).
Перечитайте еще раз основное сообщение и увидите, что речь шла изначально об обнулении структур (то есть о забитии участка памяти нулями а не об инициализации как таковой). Имелись в виду структуры с примитивными типами данных — char, short, int, long и их знаковые и беззнаковые версии. Никто НЕ будет инициализировать структуру с типами, определенными пользователем, через ZeroMemory(), и, более того, что делать если у такого типа нету конструктора по умолчанию? Правильно, нужно будет написать свой конструктор для "общей" структуры и там уже вызывать имеющийся конструктор, а имея хотя бы один конструктор, уже нельзя инициализировать структуру через фигурные скобки!
Такой подход, как Вы и сами знаете, порядком используется в сетевом коде — обнуляют просто структуру целиком а затем уже устанавливают нужные элементы, типы данных которых уже приведены выше, и где Вы там видели числа с правающей точкой не говоря уже о user-defined data types? Зачем лезть в "дебри ООП?"
Это тебе не мешало бы перечитать исходное сообщение, свое, и ответ Павла.
А когда говоришь про стандарт, старайся все таки на самом деле заглянуть в него, чтоб не сесть в лужу.
int аrr[10] = {};
Если следовать твоему "стандарту", то, видимо, никакой инициализации тут нет.
Кстати, для "примитивных" типов нулевое значение в какой-то реализации может быть вовсе не набором нулевых битов.
Of course, the code must be complete enough to compile and link.
Re[5]: ZeroMemory vs xxx = { 0 };
От:
Аноним
Дата:
12.06.04 16:54
Оценка:
L_L>Это тебе не мешало бы перечитать исходное сообщение, свое, и ответ Павла.
И что мне там перечитать? То, что мне Павел говорит, что нехорошо "инициализировать" обьекты через ZeroMemory()? Это я и так знаю.
L_L>А когда говоришь про стандарт, старайся все таки на самом деле заглянуть в него, чтоб не сесть в лужу. L_L>
L_L>int аrr[10] = {};
L_L>
L_L>Если следовать твоему "стандарту", то, видимо, никакой инициализации тут нет.
Сейчас нет ни книги не компилятора под рукой. Приведи этот пункт, будь добр.
L_L>Кстати, для "примитивных" типов нулевое значение в какой-то реализации может быть вовсе не набором нулевых битов.
Это я тоже знаю. Я НЕ говорил о том, что при забитии структуры нулями, например char * будет NULL! Все что я сказал, это то, что участок памяти отведенной под структуру будет забит нулями! Все! Дальше уже дело программиста правильно установить этот указатель. Где ты вычитал, что я, якобы, говорил, что для примитивных типов значение ноль всегда соответсвует набору нулевых битов?
> Имелись в виду структуры с примитивными типами данных — char, short, int, long и их знаковые и беззнаковые версии.
В оригинальном сообщении ничего не было о подобных ограничениях. В противном случае, приведи цитату, пожалуйста.
> Никто НЕ будет инициализировать структуру с типами, определенными пользователем, через ZeroMemory()
Структура или перечислимый тип — варианты типов, определяемых пользователем. Таким образом ты говоришь, что обнулять структуры с членами-структурами или перечислениями тоже никто не будет?
Но, вообще, дело не в том, что будут или не будут делать изначально. Член "неправильного" типа вполне может появиться позднее, при модификации структуры. И в этом случае memset покажет себя не с лучшей стороны.
> и, более того, что делать если у такого типа нету конструктора по умолчанию?
Тем более хороший аргумент. В случае использования инициализатора компилятор сразу сообщит о неверном "обнулении". В случае же с memset, тебе придется полагаться на провидение.
> Такой подход, как Вы и сами знаете, порядком используется в сетевом коде — обнуляют просто структуру целиком а затем уже устанавливают нужные элементы, типы данных которых уже приведены выше, и где Вы там видели числа с правающей точкой не говоря уже о user-defined data types?
Обнуление структур используется много где. И в том числе, например, в работе с API Windows, пример чего был в исходном сообщении, или в работе с DirectX. И там, и там в структурах присутствуют члены типа float.
Posted via RSDN NNTP Server 1.9 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
> Это я тоже знаю. Я НЕ говорил о том, что при забитии структуры нулями, например char * будет NULL!
Строго говоря, это относится не только к указателям, но и к целочисленным типам.
> Все что я сказал, это то, что участок памяти отведенной под структуру будет забит нулями! Все!
И каков смысл такого "обнуления"?
Posted via RSDN NNTP Server 1.9 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: ZeroMemory vs xxx = { 0 };
От:
Аноним
Дата:
12.06.04 17:55
Оценка:
>> Имелись в виду структуры с примитивными типами данных — char, short, int, long и их знаковые и беззнаковые версии. ПК>В оригинальном сообщении ничего не было о подобных ограничениях. В противном случае, приведи цитату, пожалуйста.
Давайте вначале разберемся с экземлярами классов, а до перечислений дойдем позже. Допустим у нас в структуре есть обьект класса. Теперь скажите, как часто в своей практике Вы инициализируете подобную структуру через фигурные скобки? Думаю, что все-таки не часто.
В таком случае лучше написать свой конструктор, который бы вызывал конструктор для создания названного обьекта. Если же у этого класса нету конструктора по умолчанию, то мы просто обязаны написать свой конструктор для нашей структуры. Таким образом, имея хотя бы один конструктор (структуры), мы уже никак не можем инициализировать ее через фигурные скобки. Из всего этого, можно заключить, что фигурные скобки используются для инициализации структур, члены которых являются примитивными типами данных, что на практике так и делается (т.е. классы используется для более высокоуровневых конструкций и имеют конструкторы, в то время как структуры обычно инкапсулируют примитивные типы данных и не имеют конструкторов).
Более того, сам Дарней пишет, что "привык писать обнуление структур в таком-то виде," но в том-то и дело, что что значит "обнуление" для обьектов пользовательских типов? Согласитесь, этот низко-уровневый термин не очень-то применим к высоко-уровневым обьектам, что в свою очередь значит, обычное низко-уровневое забивание участка памяти нулями (и которое ни в коем случае НЕ является инициализацией). Так получается, что семантика этого низко-уровнего забивания памяти соответствует инициализации нулем для большинства примитивных типов, как Вы уже это и заметили.
>> Никто НЕ будет инициализировать структуру с типами, определенными пользователем, через ZeroMemory() ПК>Структура или перечислимый тип — варианты типов, определяемых пользователем. Таким образом ты говоришь, что обнулять структуры с членами-структурами или перечислениями тоже никто не будет?
Согласитесь, класс — более высокоуровневая конструкция чем обычный enum. Что нам мешает забить этот enum нулями (даже если переменная после забития будет иметь illegal state) а затем установить уже легальное значение для этого перечисления?
ПК>Но, вообще, дело не в том, что будут или не будут делать изначально. Член "неправильного" типа вполне может появиться позднее, при модификации структуры. И в этом случае memset покажет себя не с лучшей стороны.
Если у нас в структуре появляется член "неправильного" типа, то сама структура становится "неправильным" типом, и очевидно, что не хорошо использовать низкоуровневую memset() для "обнуления" структуры т.к. непонятно что же все-таки значит это обнуление. Именно по аналогичной причине нельзя использовать обьекты классов в юнионах — т.к. неизвестно какой деструктор нужно будет вызвать.
>> и, более того, что делать если у такого типа нету конструктора по умолчанию? ПК>Тем более хороший аргумент. В случае использования инициализатора компилятор сразу сообщит о неверном "обнулении". В случае же с memset, тебе придется полагаться на провидение.
Да никакого провидения! Это ошибка если используется memset() на "неправильном" типе.
>> Такой подход, как Вы и сами знаете, порядком используется в сетевом коде — обнуляют просто структуру целиком а затем уже устанавливают нужные элементы, типы данных которых уже приведены выше, и где Вы там видели числа с правающей точкой не говоря уже о user-defined data types?
ПК>Обнуление структур используется много где. И в том числе, например, в работе с API Windows, пример чего был в исходном сообщении, или в работе с DirectX. И там, и там в структурах присутствуют члены типа float.
Ага! Про ДиректХ ничего не знаю, но позволю себе заметить, что НИ в одной структуре Вин АПИ нету обьектов классов! Поэтому можно и использовать memset(). На счет флоутов — Вы уверены, что ноль флоута не является нулевым набором битов для Интеловской архитектуры? Или может быть все-таки в некоторых вызовах значения этих флоутов не принимаются во внимание?
Уфф... Чувствую себя так, словно lawyer проводящий защиту! Перечитывать уже не хочу ничего.
Re[7]: ZeroMemory vs xxx = { 0 };
От:
Аноним
Дата:
12.06.04 18:11
Оценка:
ПК>Строго говоря, это относится не только к указателям, но и к целочисленным типам.
Раз уж мы вдались в дебри юриспруденции языков программирования, то можете привести ссылку на этот "факт?" Насколько я знаю, на всех машинах int 0 будет всегда нулевым набором бит (другое дело разница между big-endian и little-endian архитектурами, но это совсем не то). 0 float или double может не быть нулевым набором бит (нужно читать стандарт IEEE 754 ) точно также как 0 void * может не быть нулевым набором бит.
>> Все что я сказал, это то, что участок памяти отведенной под структуру будет забит нулями! Все! ПК>И каков смысл такого "обнуления"?
Смысл в том, что для многих встроенных типов семантика такого обнуления равна семантике инициализации нулем. Вместого того, чтобы писать = 0; для кучи переменных типа int проще сразу забить всю структуру нулями а затем уже подкоректировать "некоторые оставшиеся" переменные, дав им нужные значения. Все! Это я и имел в виду!
Re[5]: ZeroMemory vs xxx = { 0 };
От:
Аноним
Дата:
12.06.04 18:17
Оценка:
L_L>А когда говоришь про стандарт, старайся все таки на самом деле заглянуть в него, чтоб не сесть в лужу. L_L>
L_L>int аrr[10] = {};
L_L>
L_L>Если следовать твоему "стандарту", то, видимо, никакой инициализации тут нет.
Ок. Должен частично признать свою ошибку. gcc скомпилировал этот код без проблем, и все элементы действительно были равны нулю. Visual C++ 6.0 SP 5 отказался компилировать. Поставив один элемент между скобками, код скомпилировался. Нулевой элемент был равен установленому значению, а все оставшиеся были равны нулю.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Обнуление структур используется много где. И в том числе, например, в работе с API Windows, пример чего был в исходном сообщении, или в работе с DirectX. И там, и там в структурах присутствуют члены типа float.
Ничего страшного. И float и double пердставляют положительный нуль нулевой цепочкой байт. Это, конечно, особенность архитектуры, но эта особенность соответствует стандарту IEEE 754.
Вообще, с чисто практической точки зрения системы, где фундаментальные типы данных имеют нулевые значения, представимые ненулевой цепочкой байт, менее юзабельны. Я, кстати, ни одной современной такой системы не знаю.
Ну, например. Перед началом программы, все статические неинициализировные явно переменные должны быть обнулены. Проще всего это сделать, собрав их в одну секцию и натравив на неё memset.
Типично, компилятор собирает такие переменные в секцию .bss. Эта секция не имеет тела -- соответственно, не занимает памяти в объектнике/экзешнике, не нужно грузить её в память при загрузке и.т.п.
Просто стартап-код вытирает её в начале работы программы -- и всё. Просто, эффективно. Ну а поскольку человек -- существо ленивое ... Вообщем лень -- двигатель не только прогресса, но и стандартизации.
> ПК> дело не в том, что будут или не будут делать изначально. Член "неправильного" типа вполне может появиться позднее, при модификации структуры. И в этом случае memset покажет себя не с лучшей стороны.
> Если у нас в структуре появляется член "неправильного" типа, то сама структура становится "неправильным" типом, и очевидно, что не хорошо использовать низкоуровневую memset() для "обнуления" структуры т.к. непонятно что же все-таки значит это обнуление.
Ч.т.д.: "обнуление" с помощью memset в ряде случаев некорректно, при этом "обнуление" инициализатором либо делает, что ожидается, либо приводит к ошибке компиляции. Что непонятно-то?
> ПК>Тем более хороший аргумент. В случае использования инициализатора компилятор сразу сообщит о неверном "обнулении". В случае же с memset, тебе придется полагаться на провидение.
> Да никакого провидения! Это ошибка если используется memset() на "неправильном" типе.
Только никто об этой "ошибке" тебе не скажет. Например: была когда-то структура, в которой, скажем, был член const char*, и кто-то "обнулял" ее с помощью memset, а впоследствии член был заменен, скажем, на std::string.
> НИ в одной структуре Вин АПИ нету обьектов классов! Поэтому можно и использовать memset().
Хорошо, уговорил. Используй Только другим не навязывай.
> На счет флоутов — Вы уверены, что ноль флоута не является нулевым набором битов для Интеловской архитектуры? Или может быть все-таки в некоторых вызовах значения этих флоутов не принимаются во внимание?
А причем здесь Интел? Я тебе просто привел относительно типичные API, где часто используется "обнуление". Просто в ответ на твоё заявление о том, что, дескать, такой код используется в каком-то сетевом коде. Такая же петрушка есть на любой платформе, в т.ч. и на тех, где побайтное обнуление для плавающих типов не означает ничего осмысленного.
Posted via RSDN NNTP Server 1.9 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
> Ничего страшного. И float и double пердставляют положительный нуль нулевой цепочкой байт. Это, конечно, особенность архитектуры, но эта особенность соответствует стандарту IEEE 754.
Да, конечно. Никто и не утверждал обратного.
Posted via RSDN NNTP Server 1.9 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, <Аноним>, Вы писали:
ПК>>Строго говоря, это относится не только к указателям, но и к целочисленным типам. А>Раз уж мы вдались в дебри юриспруденции языков программирования, то можете привести ссылку на этот "факт?" Насколько я знаю, на всех машинах int 0 будет всегда нулевым набором бит (другое дело разница между big-endian и little-endian архитектурами, но это совсем не то). 0 float или double может не быть нулевым набором бит (нужно читать стандарт IEEE 754 )
Будет. Вот по IEEE 754 и будет.
А> точно также как 0 void * может не быть нулевым набором бит.
Обычно, тоже будет.
>>> Все что я сказал, это то, что участок памяти отведенной под структуру будет забит нулями! Все! ПК>>И каков смысл такого "обнуления"? А>Смысл в том, что для многих встроенных типов семантика такого обнуления равна семантике инициализации нулем. Вместого того, чтобы писать = 0; для кучи переменных типа int проще сразу забить всю структуру нулями а затем уже подкоректировать "некоторые оставшиеся" переменные, дав им нужные значения. Все! Это я и имел в виду!
ПК>Только никто об этой "ошибке" тебе не скажет. Например: была когда-то структура, в которой, скажем, был член const char*, и кто-то "обнулял" ее с помощью memset, а впоследствии член был заменен, скажем, на std::string.
Ок. У меня Visual C++ SP 5. Думаете он скомпилирует следущий код если убрать комментарий?
Ответ: нет! Не знаю по стандарту это или нет и даже не хочу вникать! Я бы никогда так не инициализировал такой обьект!
Так что даже в этом случае нужен конструктор и так просто замена указателя на строку не скомпилируется (по крайней мере для этого компилятора)! В том коде, что предложил Дарней программитсты используют синтаксис инициализации, чтобы забить кусок памяти, выделяемой под обьект, нулями а не чтобы инициализировать члены структуры значениями по умолчанию! В противном случае можно было бы создать default constructor и не мучиться с фигурными скобками!
Вот встречный вопрос: если же мы говорим тут об инициализации обьектов (высоко-уровневой операции) а не о забивании куска памяти нулями (низко-уровневой операции), зачем вообще зашла речь о ZeroMemory()?
ПК>Хорошо, уговорил. Используй Только другим не навязывай.
Мне это не надо! Сколько бы мы тут не говорили, каждый из нас останется при своем мнении. Только Вы говорите о высокоуровневых обьектах, для которых ZeroMemory() неприемлем, а я же и автор начального топика говорим о низкоуровневом обнулении куска памяти. Подумайте об этом!
PS. Меня поражает как люди бросаются ссылками на стандарт по синтаксису, словно задались задачей знать каждую синтаксическую конструкцию языка. Только синтаксис-то и знают, а вот в вопросе является ли creat() стандартной функцией или все-таки системным вызовом тормозят. Точно также был вопрос по макросам тут из stdarg.h, так что-то не особо бросались знаниями в этом направлении.
> ПК>Только никто об этой "ошибке" тебе не скажет. Например: была когда-то структура, в которой, скажем, был член const char*, и кто-то "обнулял" ее с помощью memset, а впоследствии член был заменен, скажем, на std::string.
> Ок. У меня Visual C++ SP 5. Думаете он скомпилирует следущий код если убрать комментарий? >
Потом, когда у тебя будет предостаточно подобных "обнулений" по всему коду, член s вполне может быть заменен на std::string. И тогда компилятор и не пикнет, а у тебя останутся "мины" в виде заполнения std::string нулями.
Если бы в данном фрагменте была использована инициализация по умолчанию одним из следующих способов, предусмотренных непосредственно языком:
SomeStruct s = SomeStruct();
SomeStruct s = { 0 };
Или даже так, если компилятор поновее:
SomeStruct s = { };
то, при изменении типа s на std::string, либо компилятор бы "возмутился" (нестандартное поведение, но в данном случае это не важно — главное, что ерунду не начнет делать), либо бы продолжал делать правильную вещь.
Таким образом, вопреки твоим прежним заявлениям, использование ZeroMemory вовсе не лучше, чем использование инициализатора. Скорее даже наоборот. Что еще-то до сих пор непонятно?
> ПК>Хорошо, уговорил. Используй Только другим не навязывай.
> Мне это не надо!
Тогда как понимать это твое утверждение?
Лучше использовать ZeroMemory()
> Сколько бы мы тут не говорили, каждый из нас останется при своем мнении.
Мнения тут совершенно ни при чем; это не фасон платья, где уместны суждения: нравится — не нравится. Здесь все просто, как дважды два: есть два подхода к "обнулению" агрегатов. Один предусмотрен языком, и его использование контролируется компилятором. Второй, при том, что ничего к первому не добавляет, непосредственно языком не гарантируется, компилятором не поддерживается, и, соответственно, является менее безопасным. Какие тут могут быть мнения?
> Только Вы говорите о высокоуровневых обьектах, для которых ZeroMemory() неприемлем,
Нет, я говорю о том, какой из двух способов "обнуления" структур более предпочтителен в аналогичных случаях.
> а я же и автор начального топика говорим о низкоуровневом обнулении куска памяти.
От автора оригинального сообщения я подобных заявлений не слышал. Да и какой смысл в абстрактном "низкоуровневом обнулении куска памяти", если оно не означает обнуление всех элементов структуры?
> PS. Меня поражает как люди бросаются ссылками на стандарт по синтаксису словно задались задачей знать каждую синтаксическую конструкцию языка. Только синтаксис-то и знают, а вот в вопросе является ли creat() стандартной функцией или все-таки системным вызовом тормозят. Точно также был вопрос по макросам тут из stdarg.h, так что-то не особо бросались знаниями в этом направлении.
Переход на обсуждение знаний собеседников или других участников форума, мало того, что ничего конструктивного в дискуссию не привносит, так еще и прямо запрещен правилами форумов РСДН.
> PPS. У Вас, Павел, указан неверный автор цитаты!
Настолько верный, насколько верно его указал Кнут, которому эту цитату часто ошибочно приписывают.
Posted via RSDN NNTP Server 1.9 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[9]: ZeroMemory vs xxx = { 0 };
От:
Аноним
Дата:
13.06.04 02:51
Оценка:
Мы говорим о Фоме и о Ереме... ПК>Ты невнимательно читаешь то, что я тебе пишу. Еще раз. Вот такой объект ты не возражаешь так инициализировать? ПК>
Да поймите Вы! Я НЕ говорю об инициализации обьекта! Инициализация поддерживается самим языком, а этот вызов, о котором мы так долго спорим и который Вы только что привели — просто обнуляет кусок памяти, выделенный для s.
ПК>Потом, когда у тебя будет предостаточно подобных "обнулений" по всему коду, член s вполне может быть заменен на std::string. И тогда компилятор и не пикнет, а у тебя останутся "мины" в виде заполнения std::string нулями.
И это я тоже понимаю! Только если Вы замените потом указатель на строку, то получается, что изначально дизайн был корявый, и мины вовсе не потому, что используется ZeroMemory() на string'ах, а из-за недостаточного планирования. Поэтому я и говорю, что ZeroMemory() можно использовать на структурах без классов.
ПК>Таким образом, вопреки твоим прежним заявлениям, использование ZeroMemory вовсе не лучше, чем использование инициализатора. Скорее даже наоборот. Что еще-то до сих пор непонятно?
Опять-таки, ZeroMemory() НЕ инициализрует обьект, и, разумеется это ошибка, использовать эту функция на структурах с классами.
ПК>Тогда как понимать это твое утверждение? ПК>
ПК>Лучше использовать ZeroMemory()
Забудьте про С++! Только С! У вас есть примерно такая структура:
struct packet {
unsigned short packet_len;
unsigned short flags;
union {
char text[100];
...
} u;
...
char reserved[8]; /* must be zero */
} packet;
Перед тем как заполнять эту структуру, имеет смысл ее обнулить (установить reserved в ноль, сбросить флаги и т.д.). Как бы Вы сделали? Я бы через ZeroMemory() обнулил всю структуру зараз а не struct packet packet = { 0 }; Ричард Стивенс так и делает, и по-моему у него есть какой-то комментарий на счет последнего стиля.
А затем через sendto() просто послать ее в сеть. Все sizeof packet байт! А если б std::string был, то посылка была бы сложнее. Вы применили классы и OOП к тому случаю где они совсем не нужны, и разговор давно уже свернул в другую плоскость. Вы говорите о высоко-уровневом коде (каким и должен быть С++) а я говорю о низко-уровневом (какой и есть С).
ПК>Мнения тут совершенно ни при чем; это не фасон платья, где уместны суждения: нравится — не нравится. Здесь все просто, как дважды два: есть два подхода к "обнулению" агрегатов. Один предусмотрен языком, и его использование контролируется компилятором. Второй, при том, что ничего к первому не добавляет, непосредственно языком не гарантируется, компилятором не поддерживается, и, соответственно, является менее безопасным. Какие тут могут быть мнения?
Все это так! Вы абсолютно правы! Только использование ZeroMemory() будет абсолютно безопасным если структура содержит только примитивные типы данных. Такой код, что привел Дарней используется на самом низком уровне системы. Сколько раз Вы инициализировали экземпляры классов через фигурные скобки? Думаю что ноль! А добавив std::string в такую структуру, она сама становится "высокоуровневым классом." (обратите внимание на скобки — я не говорю о конкретной реализации)
ПК>Нет, я говорю о том, какой из двух способов "обнуления" структур более предпочтителен в аналогичных случаях.
Да поймите Вы, обнуляют структуры только на низком уровне, и разумеется этот метод неприемлим для "сложных обьектов."
>> а я же и автор начального топика говорим о низкоуровневом обнулении куска памяти. ПК>От автора оригинального сообщения я подобных заявлений не слышал. Да и какой смысл в абстрактном "низкоуровневом обнулении куска памяти", если оно не означает обнуление всех элементов структуры?
I give up! Лучше выпьем и прекратим все эти споры ни о чем!
ПК>Переход на обсуждение знаний собеседников или других участников форума, мало того, что ничего конструктивного в дискуссию не привносит, так еще и прямо запрещен правилами форумов РСДН.
Сорри! Просто я полностью согласен со Страуструпом, что не нужно знать каждую черту языка, чтобы успешно программировать, а тут такие лойера!
ПК>Настолько верный, насколько верно его указал Кнут, которому эту цитату часто ошибочно приписывают.
Напишем Страуструпу, что он ошибся в авторстве этой цитаты?
> Перед тем как заполнять эту структуру, имеет смысл ее обнулить (установить reserved в ноль, сбросить флаги и т.д.). Как бы Вы сделали? Я бы через ZeroMemory() обнулил всю структуру зараз а не struct packet packet = { 0 }; Ричард Стивенс так и делает, и по-моему у него есть какой-то комментарий на счет последнего стиля.
Итак, правильно ли я понял, что единственным аргументом в пользу ZeroMemory() vs. { 0 } является то, что так делает некий Ричард Стивенс?
Posted via RSDN NNTP Server 1.9 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Аноним, Вы писали:
ПК>>Строго говоря, это относится не только к указателям, но и к целочисленным типам. А>Раз уж мы вдались в дебри юриспруденции языков программирования, то можете привести ссылку на этот "факт?" Насколько я знаю, на всех машинах int 0 будет всегда нулевым набором бит (другое дело разница между big-endian и little-endian архитектурами, но это совсем не то).
Стандарт языка этого не гарантирует. Помнится кто-то в Usenet-е даже упоминал реальную платформу, в которой использовался "бит нечетности".
А>0 float или double может не быть нулевым набором бит (нужно читать стандарт IEEE 754
Стандарт IEEE 754 никакого отношения к стандартам С и С++ не имеет.
А> точно также как 0 void * может не быть нулевым набором бит.
А это уже полный бред. Примеров платформ, в который null-pointer value задается ненулевым набором бит — вагон и маленькая тележка. Сделай поиск по Google Groups — там их навалом приводится.
Здравствуйте, Аноним, Вы писали: А>Перед тем как заполнять эту структуру, имеет смысл ее обнулить (установить reserved в ноль, сбросить флаги и т.д.). Как бы Вы сделали? Я бы через ZeroMemory() обнулил всю структуру зараз а не struct packet packet = { 0 }; Ричард Стивенс так и делает, и по-моему у него есть какой-то комментарий на счет последнего стиля.
Обнуление при помощи '={0}' тоже обнуляет всю структуру сразу в тех ситуациях, когда это возможно. Если какому-то компилятору вдруг захотелось "разбить" процесс обнуления каким-то неоптимальным образом — это проблемы этого компилятора, а не способа '={0}'.
А>Все это так! Вы абсолютно правы! Только использование ZeroMemory() будет абсолютно безопасным если структура содержит только примитивные типы данных.
Это бред. Абсолютно безопасным это является только для char типов. Это станет безопасным для боее широко числа интегральных типов в языке C99, когда выйдет соответствующая коррекция (если выйдет). Для плавающих типов, типов указателей и остальных это не будет безопасным никогда (по краней мере пока такой безопасностью даже и не пахнет).
А>Такой код, что привел Дарней используется на самом низком уровне системы. Сколько раз Вы инициализировали экземпляры классов через фигурные скобки? Думаю что ноль!
А я вот — инициализировал и очень много раз. Доктор, я — феномен?
А>А добавив std::string в такую структуру, она сама становится "высокоуровневым классом." (обратите внимание на скобки — я не говорю о конкретной реализации)
И тем не менее в этом конкретном случае все еще допускает инициализацию вида 'S s = s()'. Это будет по-прежнему выполнять обнуление всего того, для чего обнуление является умолчательной инициализацией. Всякие 'ZeroMemory' тут совсем отдыхают.
ПК>>Нет, я говорю о том, какой из двух способов "обнуления" структур более предпочтителен в аналогичных случаях. А>Да поймите Вы, обнуляют структуры только на низком уровне, и разумеется этот метод неприемлим для "сложных обьектов."
Обнуляют структцры на разных уровнях. Только вот всяких 'ZeroMemory' стараются избежать всегда, когда это возможно.
ПК>>Переход на обсуждение знаний собеседников или других участников форума, мало того, что ничего конструктивного в дискуссию не привносит, так еще и прямо запрещен правилами форумов РСДН. А>Сорри! Просто я полностью согласен со Страуструпом, что не нужно знать каждую черту языка, чтобы успешно программировать, а тут такие лойера!
"Программировать" — понятие весьма и весьма растяжимое.
"Андрей Тарасевич" <2174@news.rsdn.ru> wrote in message news:678449@news.rsdn.ru...
> ПК>>Строго говоря, это относится не только к указателям, но и к целочисленным типам. > А>Раз уж мы вдались в дебри юриспруденции языков программирования, то можете привести ссылку на этот "факт?" Насколько я знаю, на всех машинах int 0 будет всегда нулевым набором бит (другое дело разница между big-endian и little-endian архитектурами, но это совсем не то). > > Стандарт языка этого не гарантирует. Помнится кто-то в Usenet-е даже упоминал реальную платформу, в которой использовался "бит нечетности".
Огромное количество кода на Си заложено на то, что нули целочисленных типов представляются наборами сброшенных битов. Если действительно есть платформа, для которой это не так, то это, главным образом, проблема такой платформы, но не существующего кода.
Вся история использования функции calloc работает против таких платформ.
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>Здравствуйте, Аноним, Вы писали:
ПК>>>Строго говоря, это относится не только к указателям, но и к целочисленным типам. А>>Раз уж мы вдались в дебри юриспруденции языков программирования, то можете привести ссылку на этот "факт?" Насколько я знаю, на всех машинах int 0 будет всегда нулевым набором бит (другое дело разница между big-endian и little-endian архитектурами, но это совсем не то).
АТ>Стандарт языка этого не гарантирует. Помнится кто-то в Usenet-е даже упоминал реальную платформу, в которой использовался "бит нечетности".
А>>0 float или double может не быть нулевым набором бит (нужно читать стандарт IEEE 754
АТ>Стандарт IEEE 754 никакого отношения к стандартам С и С++ не имеет.
А>> точно также как 0 void * может не быть нулевым набором бит.
АТ>А это уже полный бред. Примеров платформ, в который null-pointer value задается ненулевым набором бит — вагон и маленькая тележка. Сделай поиск по Google Groups — там их навалом приводится.
Все круты — линейку в студию!!!!
Слушайте люди, вам что потрепаться хочется? Чего к человеку привязались? Вы изначальный вопрос прочитайте внимательно! Вас спросили, что лучше ZeroMemory или ={0}. Функция ZeroMemory присутсвует единственной платформе — Win32, и на этой платформе и null-pointer value равен 0 (точнее даже так: значение указателя равное 0 — это есть null-pointer value), и int 0 есть набор сброшенных битов. Причём здесь различные платформы, где есть бит нечётности или ещё что-нть в этом роде. А вот то, что на этой платформе в некоторых компиляторах ={0} может не занулить всю структуру — в это я могу поверить (я не утверждаю, что это так, но и не утверждаю что так не будет в будущем). Поэтому IMHO лучше ZeroMemory или ещё лучше memset(&dst, 0, sizeof(dst)).
Если кого обидел — звиняйте не хотел — просто наболело
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
> Функция ZeroMemory присутсвует единственной платформе — Win32, и на этой платформе и null-pointer value равен 0 <...>
Если ты тему читал невнимательно, напомню, что помимо этого, второстепенного, аспекта, есть еще и основной — использование UDT.
> А вот то, что на этой платформе в некоторых компиляторах ={0} может не занулить всю структуру — в это я могу поверить (я не утверждаю, что это так, но и не утверждаю что так не будет в будущем)
Т.е. ты попросту не знаешь. Соответственно, опираться на это положение в своих рассуждениях неразумно.
> Поэтому IMHO лучше ZeroMemory или ещё лучше memset(&dst, 0, sizeof(dst)).
До добавления первого UDT в структуру.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Дарней, Вы писали:
Д>Признаюсь честно, привык писать обнуление структур в таком стиле:
Д> WNDCLASSEX wcx = { 0 };
Д>Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак Д>Интересно — может быть, есть какие-то аргументы против такой практики?
Работаю только на win32, поэтому о переносе на другие платформы не задумывался. Здорово здесь то, что для проекта ATL 7.0 можно включить опцию Minimize CRT Use in ATL, что делает скомпилированный код меньше процентов на 10...15, и не нужно таскать за собой библиотеку msvcr70.dll. Кто что скажет?
Лечение насморка отрубанием головы: зачем использовать кучу там, где можно обойтись выделением памяти "в стеке"?
> Работаю только на win32, поэтому о переносе на другие платформы не задумывался.
Эквивалентное "решение", работающее и на других платформах — calloc.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Mr. None, Вы писали:
MN>Слушайте люди, вам что потрепаться хочется? Чего к человеку привязались? Вы изначальный вопрос прочитайте внимательно! Вас спросили, что лучше ZeroMemory или ={0}. Функция ZeroMemory присутсвует единственной платформе — Win32, и на этой платформе и null-pointer value равен 0 (точнее даже так: значение указателя равное 0 — это есть null-pointer value), и int 0 есть набор сброшенных битов.
Ну тут следует сразу заметить, что в рамках языка С++ термин "платформа" является эквивалентом термина "реализация", а не термина "аппаратная часть" или "оперционная система" как часто ошибочно полагают. Поэтому если ты уже здесь заговорил о платформе, то это — MSVC++ 6 (или какой там имелся в виду) для Win32, а не сама Win32.
Строго говоря, в официальной теминологии языка С++ вообще нет термина "платформа", а во всех соответствующих местах используется именно термин "реализация". В этом пристутвует очевидная логика — конкретная реализация (компилятор) если захочет, может запросто использовать физически ненулевые null-pointer values, физически ненулевые нули целочисленных типов, обратный код для представления отрицательных чисел (вместо дополнительного), отличный от IEEE 754 формат представления плавающих чисел и т.п. выкрунтасы, даже если все это идет вразрез с соглашениями используемой ОС и аппаратуры — т.е. все на той же x86 Win32. Это неэффективно, но тем не менее все это можно достаточно очевидным образом реализовать и заставить работать. Хотя интерес такая реализация если и будет представлять то, наверное, чисто теоретический.
MN>Причём здесь различные платформы, где есть бит нечётности или ещё что-нть в этом роде.
Да, если задаться целью, можно реализовать такую C++ платформу и для x86 Win32.
MN>А вот то, что на этой платформе в некоторых компиляторах ={0} может не занулить всю структуру — в это я могу поверить (я не утверждаю, что это так, но и не утверждаю что так не будет в будущем). Поэтому IMHO лучше ZeroMemory или ещё лучше memset(&dst, 0, sizeof(dst)).
Если какой-то компилятор не занулит всю струкутру по '={0}', то не удивляйся, если такой компилятор будет произвольным образом падать на 'memset(&dst, 0, sizeof dst)'.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Если ты тему читал невнимательно, напомню, что помимо этого, второстепенного, аспекта, есть еще и основной — использование UDT.
>> А вот то, что на этой платформе в некоторых компиляторах ={0} может не занулить всю структуру — в это я могу поверить (я не утверждаю, что это так, но и не утверждаю что так не будет в будущем)
ПК>Т.е. ты попросту не знаешь. Соответственно, опираться на это положение в своих рассуждениях неразумно.
>> Поэтому IMHO лучше ZeroMemory или ещё лучше memset(&dst, 0, sizeof(dst)).
ПК>До добавления первого UDT в структуру.
Я читал тему внимательно, в том числе внимательно читал и первый вопрос — WNDCLASSEX не содержит UDT... ZeroMemory или memset можно и иногда даже нужно применять в отношении любых структур не содержащих UDT, в частности структур используемых в низкоуровневом коде, работающим с голыми API-вызовами к операционной системе.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>Здравствуйте, Mr. None, Вы писали:
АТ>Ну тут следует сразу заметить, что в рамках языка С++ термин "платформа" является эквивалентом термина "реализация", а не термина "аппаратная часть" или "оперционная система" как часто ошибочно полагают. Поэтому если ты уже здесь заговорил о платформе, то это — MSVC++ 6 (или какой там имелся в виду) для Win32, а не сама Win32.
Следует заметить, что произвольная реализация C++ возможна только в операционках типа MS DOS, а в операционках класса Windows она будет очень сильно связана с возможностями и требованиями ОС.
АТ>Строго говоря, в официальной теминологии языка С++ вообще нет термина "платформа", а во всех соответствующих местах используется именно термин "реализация". В этом пристутвует очевидная логика — конкретная реализация (компилятор) если захочет, может запросто использовать физически ненулевые null-pointer values, физически ненулевые нули целочисленных типов, обратный код для представления отрицательных чисел (вместо дополнительного), отличный от IEEE 754 формат представления плавающих чисел и т.п. выкрунтасы, даже если все это идет вразрез с соглашениями используемой ОС и аппаратуры — т.е. все на той же x86 Win32.
Строго говоря функция ZeroMemory — это API-функция конкретной операционной системы и реализация компилятора тут не причём — это первое.
Второе — эта операционная система предполагает, что null-pointer value — это 0 (если быть совсем точным, то это все значения указателей, расположенных в диапазоне 0x00000000 — 0x0000FFFF). Поэтому если компилятор в качестве null-pointer value выбирает скажем 0xFFFFFFFF, любой вызов API-функции, ожадающей получение указателя проинициализированного значением null-pointer values, закончиться неудачей. Следовательно либо такой компилятор будет порождать неработоспособный код, либо надо как раз пользоваться функцией ZeroMemory, а не ={0}.
АТ>...все это можно достаточно очевидным образом реализовать и заставить работать.
Подкиньте хотя бы идею как это очевидным образом реализовать и заставить работать, если операционная система делает некоторые предположения относительно принимаемых её значений.
АТ>Да, если задаться целью, можно реализовать такую C++ платформу и для x86 Win32.
Инитересно, как в такой реализации будут интерпретироваться результаты вещественного типа, возвращаемые API-вызовами операционной системы? Или придётся ещё писать кучу функций типа float win32_float_to_this_magic_cpp_float(float)?
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Mr. None, Вы писали:
MN>Здравствуйте, Павел Кузнецов, Вы писали:
ПК>>Если ты тему читал невнимательно, напомню, что помимо этого, второстепенного, аспекта, есть еще и основной — использование UDT.
>>> А вот то, что на этой платформе в некоторых компиляторах ={0} может не занулить всю структуру — в это я могу поверить (я не утверждаю, что это так, но и не утверждаю что так не будет в будущем)
ПК>>Т.е. ты попросту не знаешь. Соответственно, опираться на это положение в своих рассуждениях неразумно.
>>> Поэтому IMHO лучше ZeroMemory или ещё лучше memset(&dst, 0, sizeof(dst)).
ПК>>До добавления первого UDT в структуру.
MN>Я читал тему внимательно, в том числе внимательно читал и первый вопрос — WNDCLASSEX не содержит UDT... ZeroMemory или memset можно и иногда даже нужно применять в отношении любых структур не содержащих UDT, в частности структур используемых в низкоуровневом коде, работающим с голыми API-вызовами к операционной системе.
Насчет можно -- да, но это делает код платформенно-зависимым. Насчет нужно -- почему именно нужно? Зачем? Откуда такая необходимость? Тем более, что компилятор, скорее всего, сгенерирует идентичный код.
Здравствуйте, Mr. None, Вы писали:
MN>Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>>Здравствуйте, Mr. None, Вы писали:
АТ>>Ну тут следует сразу заметить, что в рамках языка С++ термин "платформа" является эквивалентом термина "реализация", а не термина "аппаратная часть" или "оперционная система" как часто ошибочно полагают. Поэтому если ты уже здесь заговорил о платформе, то это — MSVC++ 6 (или какой там имелся в виду) для Win32, а не сама Win32.
MN>Следует заметить, что произвольная реализация C++ возможна только в операционках типа MS DOS, а в операционках класса Windows она будет очень сильно связана с возможностями и требованиями ОС.
Как раз наоборот. На досе особенно не разгуляешься -- системных ресурсов маловато. А вот на Виндах можно сделать любое чудо -- если есть желание повыделываться, время и деньги.
Вам ничто не мешает виртуализовать вычислительный процесс любым мыслимым способом.
АТ>>Строго говоря, в официальной теминологии языка С++ вообще нет термина "платформа", а во всех соответствующих местах используется именно термин "реализация". В этом пристутвует очевидная логика — конкретная реализация (компилятор) если захочет, может запросто использовать физически ненулевые null-pointer values, физически ненулевые нули целочисленных типов, обратный код для представления отрицательных чисел (вместо дополнительного), отличный от IEEE 754 формат представления плавающих чисел и т.п. выкрунтасы, даже если все это идет вразрез с соглашениями используемой ОС и аппаратуры — т.е. все на той же x86 Win32.
MN>Строго говоря функция ZeroMemory — это API-функция конкретной операционной системы и реализация компилятора тут не причём — это первое. MN>Второе — эта операционная система предполагает, что null-pointer value — это 0 (если быть совсем точным, то это все значения указателей, расположенных в диапазоне 0x00000000 — 0x0000FFFF). Поэтому если компилятор в качестве null-pointer value выбирает скажем 0xFFFFFFFF, любой вызов API-функции, ожадающей получение указателя проинициализированного значением null-pointer values, закончиться неудачей. Следовательно либо такой компилятор будет порождать неработоспособный код, либо надо как раз пользоваться функцией ZeroMemory, а не ={0}.
Для обращения к функциям API придётся делать адаптеры, естественно.
АТ>>...все это можно достаточно очевидным образом реализовать и заставить работать. MN>Подкиньте хотя бы идею как это очевидным образом реализовать и заставить работать, если операционная система делает некоторые предположения относительно принимаемых её значений.
АТ>>Да, если задаться целью, можно реализовать такую C++ платформу и для x86 Win32.
MN>Инитересно, как в такой реализации будут интерпретироваться результаты вещественного типа, возвращаемые API-вызовами операционной системы? Или придётся ещё писать кучу функций типа float win32_float_to_this_magic_cpp_float(float)?
Здравствуйте, Шахтер, Вы писали:
MN>>Строго говоря функция ZeroMemory — это API-функция конкретной операционной системы и реализация компилятора тут не причём — это первое. MN>>Второе — эта операционная система предполагает, что null-pointer value — это 0 (если быть совсем точным, то это все значения указателей, расположенных в диапазоне 0x00000000 — 0x0000FFFF). Поэтому если компилятор в качестве null-pointer value выбирает скажем 0xFFFFFFFF, любой вызов API-функции, ожадающей получение указателя проинициализированного значением null-pointer values, закончиться неудачей. Следовательно либо такой компилятор будет порождать неработоспособный код, либо надо как раз пользоваться функцией ZeroMemory, а не ={0}.
Ш>Для обращения к функциям API придётся делать адаптеры, естественно.
Вот только если кто-нть обойдёт эти адаптеры — абзац выйдет... И кто в данном случае будет прав? Ведь мы не взирая на рекомендации производителя Visual Studio не использовать stl в своих проектах всё равно используем (кажись когда-то в MSDN-е было такое замечание, что stl поставляется только для совместимости с другим кодом и использовать её в новых проектах не рекоменуется).
MN>>Инитересно, как в такой реализации будут интерпретироваться результаты вещественного типа, возвращаемые API-вызовами операционной системы? Или придётся ещё писать кучу функций типа float win32_float_to_this_magic_cpp_float(float)?
Ш>Ага, именно так.
МАМА!! РОДИ МЕНЯ ОБРАТНО!!!!!
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
S>Работаю только на win32, поэтому о переносе на другие платформы не задумывался. Здорово здесь то, что для проекта ATL 7.0 можно включить опцию Minimize CRT Use in ATL, что делает скомпилированный код меньше процентов на 10...15, и не нужно таскать за собой библиотеку msvcr70.dll. Кто что скажет?
Это даже не из пушки по воробьям, а стратегическим ядерным оружием
Размер уменьшится не на 10-15% а на размер CRT.
Приемлимо только для маленьких очень файлов и если важно чтобы они оставались маленькими, а кого сегодня волнуют ~100kb?
К тому же может подкачать производительность стандартного хипа для маленьких объектов...
MN>Следует заметить, что произвольная реализация C++ возможна только в операционках типа MS DOS, а в операционках класса Windows она будет очень сильно связана с возможностями и требованиями ОС.
ИМХО бред какой то?
MN>Строго говоря функция ZeroMemory — это API-функция конкретной операционной системы и реализация компилятора тут не причём — это первое.
Не совсем, вернее не всегда.
Если вы посмотрите .h файл то ZeroMemory определен макросом как memset((Destination),0,(Length)).
А memset это уже функция CRT.
MN>Второе — эта операционная система предполагает, что null-pointer value — это 0 (если быть совсем точным, то это все значения указателей, расположенных в диапазоне 0x00000000 — 0x0000FFFF). Поэтому если компилятор в качестве null-pointer value выбирает скажем 0xFFFFFFFF, любой вызов API-функции, ожадающей получение указателя проинициализированного значением null-pointer values, закончиться неудачей. Следовательно либо такой компилятор будет порождать неработоспособный код, либо надо как раз пользоваться функцией ZeroMemory, а не ={0}.
Вы не найдете такой компилятор для операционки предполагающей что null-pointer value — 0
Вообще проблема надуманная, преимущество конструкции = {0} в том что это переносимый и безопасный код.
А какое преимущество у ZeroMemory? Никаких.
Ш>>Для обращения к функциям API придётся делать адаптеры, естественно. MN>Вот только если кто-нть обойдёт эти адаптеры — абзац выйдет... И кто в данном случае будет прав? Ведь мы не взирая на рекомендации производителя Visual Studio не использовать stl в своих проектах всё равно используем (кажись когда-то в MSDN-е было такое замечание, что stl поставляется только для совместимости с другим кодом и использовать её в новых проектах не рекоменуется).
Здравствуйте, maq, Вы писали:
Ш>>>Для обращения к функциям API придётся делать адаптеры, естественно. MN>>Вот только если кто-нть обойдёт эти адаптеры — абзац выйдет... И кто в данном случае будет прав? Ведь мы не взирая на рекомендации производителя Visual Studio не использовать stl в своих проектах всё равно используем (кажись когда-то в MSDN-е было такое замечание, что stl поставляется только для совместимости с другим кодом и использовать её в новых проектах не рекоменуется).
maq>Вообще полный бред. Где вы такое вычитали?
В какой-то из старых версий MSDN`а, какой именно не помню (что-то около 2000). Если хотите можете перерыть их и найдёте, я в своё время был очень удивлён этому заявлению. Но к данному спору это не имеет никакого отношения.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, maq, Вы писали:
MN>>Следует заметить, что произвольная реализация C++ возможна только в операционках типа MS DOS, а в операционках класса Windows она будет очень сильно связана с возможностями и требованиями ОС.
maq>ИМХО бред какой то?
Пример, некоторые функции Win32 принимают вещественные числа, причём в формате IEEE 754. Если компилятор будет представлять их по другому, то огребём очень много гемороя по их преобразованию из одного формата в другой.
Ещё пример, тот же преславутый nul-pointer — в Win32 сторого определены указатели, которые вопринимаются ядром как null-pointer. А большинство WinAPI-шных функций, требующих на входе null-pointer вообще просто сравнивают их с 0.
MN>>Строго говоря функция ZeroMemory — это API-функция конкретной операционной системы и реализация компилятора тут не причём — это первое.
maq>Не совсем, вернее не всегда. maq>Если вы посмотрите .h файл то ZeroMemory определен макросом как memset((Destination),0,(Length)). maq>А memset это уже функция CRT.
Не правда... читайте внимательнее:
В memset он превращается только для платформ отличных от Win32 (например, Win16)
MN>>Второе — эта операционная система предполагает, что null-pointer value — это 0 (если быть совсем точным, то это все значения указателей, расположенных в диапазоне 0x00000000 — 0x0000FFFF). Поэтому если компилятор в качестве null-pointer value выбирает скажем 0xFFFFFFFF, любой вызов API-функции, ожадающей получение указателя проинициализированного значением null-pointer values, закончиться неудачей. Следовательно либо такой компилятор будет порождать неработоспособный код, либо надо как раз пользоваться функцией ZeroMemory, а не ={0}.
maq>Вы не найдете такой компилятор для операционки предполагающей что null-pointer value — 0
Не понял утверждения... Win32 предполагает, что null-pointer value — это в том числе 0x00. M$VC, Builder предполагают так же.
maq>Вообще проблема надуманная, преимущество конструкции = {0} в том что это переносимый и безопасный код. maq>А какое преимущество у ZeroMemory? Никаких.
Я же сказал, читайте внимательнее ветку...
Если у вас структура содержащая UDT, то тогда только ={0} или даже вообще определение конструктора по-умолчанию, который инициализаирует её правильным образом.
Но человек задал вопрос, касающийся низкоуровневого кода, взаимодействующего с API операционной системы. В таком коде фигурируют только POD-структуры, в таких случаях имеет право быть ZeroMemory или даже лучше memset — для переносимости.
Для чего это надо? Хотя бы для таких хитрожопых компиляторов, которые в отличие от операцонной системы считают что null-pointer value это не 0. Операционка же ожидает, что ей прилетит кусок памяти забитый сброшенными битами. И ей по барабану, что данный компилятор не считает такой указатель 0-вым.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Mr. None, Вы писали:
АТ>>Ну тут следует сразу заметить, что в рамках языка С++ термин "платформа" является эквивалентом термина "реализация", а не термина "аппаратная часть" или "оперционная система" как часто ошибочно полагают. Поэтому если ты уже здесь заговорил о платформе, то это — MSVC++ 6 (или какой там имелся в виду) для Win32, а не сама Win32.
MN>Следует заметить, что произвольная реализация C++ возможна только в операционках типа MS DOS, а в операционках класса Windows она будет очень сильно связана с возможностями и требованиями ОС.
Нет.
АТ>>Строго говоря, в официальной теминологии языка С++ вообще нет термина "платформа", а во всех соответствующих местах используется именно термин "реализация". В этом пристутвует очевидная логика — конкретная реализация (компилятор) если захочет, может запросто использовать физически ненулевые null-pointer values, физически ненулевые нули целочисленных типов, обратный код для представления отрицательных чисел (вместо дополнительного), отличный от IEEE 754 формат представления плавающих чисел и т.п. выкрунтасы, даже если все это идет вразрез с соглашениями используемой ОС и аппаратуры — т.е. все на той же x86 Win32.
MN>Строго говоря функция ZeroMemory — это API-функция конкретной операционной системы и реализация компилятора тут не причём — это первое.
Напомню, что речь идет не о 'ZeroMemory' как таковой, а о совместимости результатов 'ZeroMemory' с результатами обнуления, сделанными средствами именно реализации ('={0}'). Так что реализация тут очень даже причем.
MN>Второе — эта операционная система предполагает, что null-pointer value — это 0 (если быть совсем точным, то это все значения указателей, расположенных в диапазоне 0x00000000 — 0x0000FFFF).
У операционной системы нет понятия null-pointer value (NPV). Это понятие чисто языковое. Точнее, даже если таковое и имеется, то это системное понятие NPV к языковому понятию NPV никакого отношения не имеет.
MN>Поэтому если компилятор в качестве null-pointer value выбирает скажем 0xFFFFFFFF, любой вызов API-функции, ожадающей получение указателя проинициализированного значением null-pointer values, закончиться неудачей.
Ну, это уже будет некорректная реализация! Всякий раз, когда требуется переход от языкового NPV к системному NPV (и/или обратно) реализация обязана выполнить соответствующее неявное преобразование.
MN>Следовательно либо такой компилятор будет порождать неработоспособный код, либо надо как раз пользоваться функцией ZeroMemory, а не ={0}.
Вывод построен на неверной посылке.
АТ>>...все это можно достаточно очевидным образом реализовать и заставить работать. MN>Подкиньте хотя бы идею как это очевидным образом реализовать и заставить работать, если операционная система делает некоторые предположения относительно принимаемых её значений.
Реализация, разумеется, обязана знать об этих предположениях и выполнять конверсию представлений из языковых в системные и обратно при переходе границы программа-система в ту или иную сторону.
АТ>>Да, если задаться целью, можно реализовать такую C++ платформу и для x86 Win32.
MN>Инитересно, как в такой реализации будут интерпретироваться результаты вещественного типа, возвращаемые API-вызовами операционной системы? Или придётся ещё писать кучу функций типа float win32_float_to_this_magic_cpp_float(float)?
В смысле "писать"? Кому придется? Реализация, разумеется, должна уметь выполнять все необходимые преобразования прозрачно для пользователя. С помощью именно вот таких функций, например.
Здравствуйте, Mr. None, Вы писали: Ш>>Для обращения к функциям API придётся делать адаптеры, естественно. MN>Вот только если кто-нть обойдёт эти адаптеры — абзац выйдет... И кто в данном случае будет прав?
В смысле "обойдет"? Обойдет хаками? Ну так сам виноват. В таком случае это вопрос не заслуживает даже и упоминания.
MN>Ведь мы не взирая на рекомендации производителя Visual Studio не использовать stl в своих проектах всё равно используем (кажись когда-то в MSDN-е было такое замечание, что stl поставляется только для совместимости с другим кодом и использовать её в новых проектах не рекоменуется).
Скорее всего речь шла о поставке двух альтернативных версий STL — старой и новой. И именно о старой говорилось, что она поставляется только для совместимости со старым кодом и использовать ее в новых проектах не рекомендуется.
MN>>>Инитересно, как в такой реализации будут интерпретироваться результаты вещественного типа, возвращаемые API-вызовами операционной системы? Или придётся ещё писать кучу функций типа float win32_float_to_this_magic_cpp_float(float)?
Ш>>Ага, именно так. MN>МАМА!! РОДИ МЕНЯ ОБРАТНО!!!!!
Здравствуйте, Андрей Тарасевич, Вы писали:
MN>>Следует заметить, что произвольная реализация C++ возможна только в операционках типа MS DOS, а в операционках класса Windows она будет очень сильно связана с возможностями и требованиями ОС.
АТ>Нет.
Вы сами себе противоречите:
АТ>Реализация, разумеется, обязана знать об этих предположениях и выполнять конверсию представлений из языковых в системные и обратно при переходе границы программа-система в ту или иную сторону.
АТ>Реализация, разумеется, должна уметь выполнять все необходимые преобразования прозрачно для пользователя. С помощью именно вот таких функций, например.
Выходит, что всё таки связана реализация с требованиями ОС...
MN>>Строго говоря функция ZeroMemory — это API-функция конкретной операционной системы и реализация компилятора тут не причём — это первое.
АТ>Напомню, что речь идет не о 'ZeroMemory' как таковой, а о совместимости результатов 'ZeroMemory' с результатами обнуления, сделанными средствами именно реализации ('={0}'). Так что реализация тут очень даже причем.
Вообще-то если я не ошибаюсь, то человек спросил о том, что лучше ={0} или ZeroMemory и нигде г-н Дарней не поднимал вопроса о совместимости результатов в первом и во втором способе. В случае POD-структур работающих с API-шными вызовами применение ZeroMemory, или memset (для переносимости), вполне правомерно. Более того в этом случае результат будет точно соответствовать требованиям операционной системы (в данном случае речь идёт о Win32) и никак не будет связан с реализацие компилятора.
Лично я использую такую практику: в модулях высокого уровня чаще всего использую конструкторы (по-умолчанию или с параметрами) или реже зануление в стиле ={0}, в модулях низкого уровня, непосредственно контактирующих со слоем API-вызовов для POD-структур из WinAPI — memset.
MN>>Второе — эта операционная система предполагает, что null-pointer value — это 0 (если быть совсем точным, то это все значения указателей, расположенных в диапазоне 0x00000000 — 0x0000FFFF).
АТ>У операционной системы нет понятия null-pointer value (NPV). Это понятие чисто языковое. Точнее, даже если таковое и имеется, то это системное понятие NPV к языковому понятию NPV никакого отношения не имеет.
Ну давайте ещё забредём в дебри рассуждений о том, что указатель вообще не обязан в точности соответствовать понятию адреса которым оперирует операционная система. И посмотрим, что у нас из этого получиться...
А в случае Win32 и многих компиляторов для этой платформы (я говорю многих, дабы не навлечь на себя новую волну возмущения, хотя IMHO — всех). Указатель — это адрес, NPV — это 0, что соответствует системному требованию налагаемому на значение NPV операционкой — любой указатель в диапазоне [0x00000000; 0x0000FFFF].
MN>>Поэтому если компилятор в качестве null-pointer value выбирает скажем 0xFFFFFFFF, любой вызов API-функции, ожадающей получение указателя проинициализированного значением null-pointer values, закончиться неудачей.
АТ>Ну, это уже будет некорректная реализация! Всякий раз, когда требуется переход от языкового NPV к системному NPV (и/или обратно) реализация обязана выполнить соответствующее неявное преобразование.
Так вы же сказали, что реализация никак не связана с платформой...
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>Здравствуйте, Mr. None, Вы писали: Ш>>>Для обращения к функциям API придётся делать адаптеры, естественно. MN>>Вот только если кто-нть обойдёт эти адаптеры — абзац выйдет... И кто в данном случае будет прав?
АТ>В смысле "обойдет"? Обойдет хаками? Ну так сам виноват. В таком случае это вопрос не заслуживает даже и упоминания.
Если эти адаптеры будут идти как функции некой внешней библиотеки, то случиться день и программист вызовет функцию API без адаптера. Если они будут встроены в компилятор на уровне языка, то это противоречит вашему утверждению о том, что реализация языка не связана с платформой для которой он предназначен.
MN>>Ведь мы не взирая на рекомендации производителя Visual Studio не использовать stl в своих проектах всё равно используем (кажись когда-то в MSDN-е было такое замечание, что stl поставляется только для совместимости с другим кодом и использовать её в новых проектах не рекоменуется).
АТ>Скорее всего речь шла о поставке двух альтернативных версий STL — старой и новой. И именно о старой говорилось, что она поставляется только для совместимости со старым кодом и использовать ее в новых проектах не рекомендуется.
Нет речь шла о политике Microsoft в отношении stl. Когда именно она изменилась не знаю, но в те времена stl в поставке шла в единственном экземпляре.
MN>>>>Инитересно, как в такой реализации будут интерпретироваться результаты вещественного типа, возвращаемые API-вызовами операционной системы? Или придётся ещё писать кучу функций типа float win32_float_to_this_magic_cpp_float(float)?
Ш>>>Ага, именно так. MN>>МАМА!! РОДИ МЕНЯ ОБРАТНО!!!!!
АТ>И? Как именно это надо понимать?
А понимать это так. Представьте, что вам каждое значение возвращённое системной функцией придётся конвертировать вот таким агрегатом: win32_float_to_this_magic_cpp_float, или таким W32F2TMCPPF... Я представил, потому как был опыт такого программизма из-за корявой реализации одного SDK.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
maq>>Если вы посмотрите .h файл то ZeroMemory определен макросом как memset((Destination),0,(Length)). maq>>А memset это уже функция CRT. MN>Не правда... читайте внимательнее: MN>
Здравствуйте, MShura, Вы писали:
maq>>>Если вы посмотрите .h файл то ZeroMemory определен макросом как memset((Destination),0,(Length)). maq>>>А memset это уже функция CRT. MN>>Не правда... читайте внимательнее: MN>>
Hello, Plague!
You wrote on Wed, 16 Jun 2004 08:16:10 GMT:
P> Здравствуйте, Дарней, Вы писали:
Д>> Признаюсь честно, привык писать обнуление структур в таком стиле: Д>> WNDCLASSEX wcx = { 0 };
P> здесь лучше так: P>
P> WNDCLASSEX wc={sizeof(WNDCLASSEX)};
P>
P>
А еще лучше так:
WNDCLASSEX ext_data = { sizeof(ext_data) };
В случае, если необходимо будет скопировать данное выражение куда нибудь..., то не придется менять
аргумент для sizeof
> мы не взирая на рекомендации производителя Visual Studio не использовать stl в своих проектах всё равно используем (кажись когда-то в MSDN-е было такое замечание, что stl поставляется только для совместимости с другим кодом и использовать её в новых проектах не рекоменуется).
Что-то многовато всевозможных "кажись". Я склонен считать это утверждение твоей выдумкой, пока не последует конкретной ссылки или цитаты из MSDN.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
>> мы не взирая на рекомендации производителя Visual Studio не использовать stl в своих проектах всё равно используем (кажись когда-то в MSDN-е было такое замечание, что stl поставляется только для совместимости с другим кодом и использовать её в новых проектах не рекоменуется).
ПК>Что-то многовато всевозможных "кажись". Я склонен считать это утверждение твоей выдумкой, пока не последует конкретной ссылки или цитаты из MSDN.
"Почему вы говорите о ней во множественном числе?" — Полосатый рейс.
Всего один "кажись". Если найду эту цитату то приведу.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
> maq>А какое преимущество у ZeroMemory? Никаких.
> Я же сказал, читайте внимательнее ветку...
Пока что преимуществ ZeroMemory в ней не видать.
> Но человек задал вопрос, касающийся низкоуровневого кода, взаимодействующего с API операционной системы.
Это твоя трактовка, не обязательно совпадающая с авторской.
> В таком коде фигурируют только POD-структуры, в таких случаях имеет право быть ZeroMemory или даже лучше memset — для переносимости. Для чего это надо? Хотя бы для таких хитрожопых компиляторов, которые в отличие от операцонной системы считают что null-pointer value это не 0.
Как уже говорилось, если такой компилятор будет на такой операционке, то он как-нибудь должен будет делать соответствующие преобразования. И если ему вместо "логического" нуля подсунут "физический", полученный с помощью memset, то в ходе этих преобразований, "физический" ноль нулем быть перестанет. В случае же "обнуления" через = { 0 }, все отработает, как ожидалось, т.к. никаких сюрпризов для компилятора мы не создавали.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
ПК>Лечение насморка отрубанием головы: зачем использовать кучу там, где можно обойтись выделением памяти "в стеке"?
Согласен, исправлюсь...
>> Работаю только на win32, поэтому о переносе на другие платформы не задумывался.
ПК>Эквивалентное "решение", работающее и на других платформах — calloc.
Здравствуйте, Mr. None, Вы писали:
MN>>>Следует заметить, что произвольная реализация C++ возможна только в операционках типа MS DOS, а в операционках класса Windows она будет очень сильно связана с возможностями и требованиями ОС.
АТ>>Нет.
Мое "нет" относилось именно к Вашему основному утверждению, что "произвольная реализация C++ возможна только в операционках типа MS DOS". Это неверное утверждение. Мое "нет" никак не относится к сопутствующим утверждениям, которые Вы предусмотрительно запихали в процитированное предложеие.
MN>Вы сами себе противоречите:
АТ>>Реализация, разумеется, обязана знать об этих предположениях и выполнять конверсию представлений из языковых в системные и обратно при переходе границы программа-система в ту или иную сторону.
АТ>>Реализация, разумеется, должна уметь выполнять все необходимые преобразования прозрачно для пользователя. С помощью именно вот таких функций, например.
MN>Выходит, что всё таки связана реализация с требованиями ОС...
Я никогда не утверждал, что реализация не связяна с требованиями ОС. Более того, с самого начала моего участия в этой дискуссии я неоднократно ссылался на существование такой связи.
MN>>>Строго говоря функция ZeroMemory — это API-функция конкретной операционной системы и реализация компилятора тут не причём — это первое.
АТ>>Напомню, что речь идет не о 'ZeroMemory' как таковой, а о совместимости результатов 'ZeroMemory' с результатами обнуления, сделанными средствами именно реализации ('={0}'). Так что реализация тут очень даже причем.
MN>Вообще-то если я не ошибаюсь, то человек спросил о том, что лучше ={0} или ZeroMemory и нигде г-н Дарней не поднимал вопроса о совместимости результатов в первом и во втором способе.
Не понял. Вопрос о том "что лучше" существует тогда и только тогда, когда существует выбор. В даном случае — выбор из двух эквивалентных (по мнению автора вопроса) способов произвести обнуление. Другими словами, на посылке совместимости результатов весь вопрос и основан. Во-первых, это посылка в общем случае неверна. Во-вторых, и даже важнее, вся соль в том, что нет никакого смысла делать что-то "хаком", если можно сделать это же корректным с точки зрения языка способом.
MN>В случае POD-структур работающих с API-шными вызовами применение ZeroMemory, или memset (для переносимости), вполне правомерно. Более того в этом случае результат будет точно соответствовать требованиям операционной системы (в данном случае речь идёт о Win32) и никак не будет связан с реализацие компилятора.
Все эти рассуждения имели бы какую-то прктическую ценность, если бы язык не предоставлял средств сделать это же без применения таких методов.
MN>Лично я использую такую практику: в модулях высокого уровня чаще всего использую конструкторы (по-умолчанию или с параметрами) или реже зануление в стиле ={0}, в модулях низкого уровня, непосредственно контактирующих со слоем API-вызовов для POD-структур из WinAPI — memset.
Не вижу оснований для этого.
MN>>>Второе — эта операционная система предполагает, что null-pointer value — это 0 (если быть совсем точным, то это все значения указателей, расположенных в диапазоне 0x00000000 — 0x0000FFFF).
АТ>>У операционной системы нет понятия null-pointer value (NPV). Это понятие чисто языковое. Точнее, даже если таковое и имеется, то это системное понятие NPV к языковому понятию NPV никакого отношения не имеет.
MN>Ну давайте ещё забредём в дебри рассуждений о том, что указатель вообще не обязан в точности соответствовать понятию адреса которым оперирует операционная система. И посмотрим, что у нас из этого получиться...
Хм... И? За примерами далено ходить не надо — во времена MS-DOS были многочисленные модели памяти, в которых языковый указатель не сответствовал системному. Да и Win32, если внимаиельно посмотреть, ситуация не сильно отличается. А если еще вспомнить указатели на члены классов — так эти вообще к операционной системе и близко не лежали...
MN>А в случае Win32 и многих компиляторов для этой платформы (я говорю многих, дабы не навлечь на себя новую волну возмущения, хотя IMHO — всех). Указатель — это адрес, NPV — это 0, что соответствует системному требованию налагаемому на значение NPV операционкой — любой указатель в диапазоне [0x00000000; 0x0000FFFF].
Это утверждение терминологически некорректно, ибо выполняет непродуманное обобщение. Например, как уже было сказано раньше, указатель типа указатель-на-член-класса не имеет никакого аналога в Win32.
MN>>>Поэтому если компилятор в качестве null-pointer value выбирает скажем 0xFFFFFFFF, любой вызов API-функции, ожадающей получение указателя проинициализированного значением null-pointer values, закончиться неудачей.
АТ>>Ну, это уже будет некорректная реализация! Всякий раз, когда требуется переход от языкового NPV к системному NPV (и/или обратно) реализация обязана выполнить соответствующее неявное преобразование.
MN>Так вы же сказали, что реализация никак не связана с платформой...
Здравствуйте, Mr. None, Вы писали:
MN>Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>>Здравствуйте, Mr. None, Вы писали: Ш>>>>Для обращения к функциям API придётся делать адаптеры, естественно. MN>>>Вот только если кто-нть обойдёт эти адаптеры — абзац выйдет... И кто в данном случае будет прав?
АТ>>В смысле "обойдет"? Обойдет хаками? Ну так сам виноват. В таком случае это вопрос не заслуживает даже и упоминания.
MN>Если эти адаптеры будут идти как функции некой внешней библиотеки, то случиться день и программист вызовет функцию API без адаптера. Если они будут встроены в компилятор на уровне языка, то это противоречит вашему утверждению о том, что реализация языка не связана с платформой для которой он предназначен.
Я такого не утверждал. Более того, я неоднократно утверждал обратное.
MN>>>>>Инитересно, как в такой реализации будут интерпретироваться результаты вещественного типа, возвращаемые API-вызовами операционной системы? Или придётся ещё писать кучу функций типа float win32_float_to_this_magic_cpp_float(float)?
Ш>>>>Ага, именно так. MN>>>МАМА!! РОДИ МЕНЯ ОБРАТНО!!!!!
АТ>>И? Как именно это надо понимать? MN>А понимать это так. Представьте, что вам каждое значение возвращённое системной функцией придётся конвертировать вот таким агрегатом: win32_float_to_this_magic_cpp_float, или таким W32F2TMCPPF... Я представил, потому как был опыт такого программизма из-за корявой реализации одного SDK.
Он бы ничем не отличался от опыта программизма в условиях корявой реализации традиционного SDK или библиотеки времени выполнения. Строго говоря, нет никакой принципиальной разницы. Современные SDK и библиотеки времени выполнения уже и сейчас выполняют соврешенно аналогичные по свой сути преобразования. Та же поддержка 'FILE*' в ОС, работающей с файлами через handles — ни что иное как именно такое преобразование. Введение дополнительных подобных конверторов ничего бы принципиально не поменяло.
Здравствуйте, Павел Кузнецов, Вы писали:
>> Но человек задал вопрос, касающийся низкоуровневого кода, взаимодействующего с API операционной системы.
ПК>Это твоя трактовка, не обязательно совпадающая с авторской.
А кто сказал, что ваша трактовка совпадает с авторской? Автор не упомянул, что его интересуют способы зануления структур в общем виде, в том числе содержащих UDT и прочее, прочее, прочее... В вопросе автора фигурировали структуры и функции WinAPI — код который может появиться исключительно в модулях самого низкого уровня приложения для ОС Windows. В них и не пахнет ни UDT, ни конструкторами ни чем другим. При ответе же на его вопрос, вомнили всё — и связанное, и не связанное. Даже переносимость кода сюда приплели, хотя о какой переносимости кода может идти речь, когда в нём присуствует WNDCLASSEX и преславутая ZeroMemory... Если уж говорить о переносимости кода между различными компиляторами в рамках одной операционки (Windows), то вариант с ZeroMemory будет более переносим.
>> В таком коде фигурируют только POD-структуры, в таких случаях имеет право быть ZeroMemory или даже лучше memset — для переносимости. Для чего это надо? Хотя бы для таких хитрожопых компиляторов, которые в отличие от операцонной системы считают что null-pointer value это не 0.
ПК>Как уже говорилось, если такой компилятор будет на такой операционке, то он как-нибудь должен будет делать соответствующие преобразования. И если ему вместо "логического" нуля подсунут "физический", полученный с помощью memset, то в ходе этих преобразований, "физический" ноль нулем быть перестанет. В случае же "обнуления" через = { 0 }, все отработает, как ожидалось, т.к. никаких сюрпризов для компилятора мы не создавали.
В таком случае библиотека WinAPI тоже должна будет соответствующим образом портирована на такой компилятор и ZeroMemory должен будет работать так как и работал везде.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Андрей Тарасевич, Вы писали:
MN>>Вообще-то если я не ошибаюсь, то человек спросил о том, что лучше ={0} или ZeroMemory и нигде г-н Дарней не поднимал вопроса о совместимости результатов в первом и во втором способе.
АТ>Не понял. Вопрос о том "что лучше" существует тогда и только тогда, когда существует выбор. В даном случае — выбор из двух эквивалентных (по мнению автора вопроса) способов произвести обнуление. Другими словами, на посылке совместимости результатов весь вопрос и основан. Во-первых, это посылка в общем случае неверна.
В том примере который привёл автор эти два способа абсолютно эквиваленты по отношению к результату.
АТ>Во-вторых, и даже важнее, вся соль в том, что нет никакого смысла делать что-то "хаком", если можно сделать это же корректным с точки зрения языка способом.
Использование ZeroMemory — это не хак а вполне корректный с точки зрения операционной системы способ зануления структуры используемой при системном вызове.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Mr. None, Вы писали:
MN>Здравствуйте, Андрей Тарасевич, Вы писали:
MN>>>Вообще-то если я не ошибаюсь, то человек спросил о том, что лучше ={0} или ZeroMemory и нигде г-н Дарней не поднимал вопроса о совместимости результатов в первом и во втором способе.
АТ>>Не понял. Вопрос о том "что лучше" существует тогда и только тогда, когда существует выбор. В даном случае — выбор из двух эквивалентных (по мнению автора вопроса) способов произвести обнуление. Другими словами, на посылке совместимости результатов весь вопрос и основан. Во-первых, это посылка в общем случае неверна.
MN>В том примере который привёл автор эти два способа абсолютно эквиваленты по отношению к результату.
АТ>>Во-вторых, и даже важнее, вся соль в том, что нет никакого смысла делать что-то "хаком", если можно сделать это же корректным с точки зрения языка способом.
MN>Использование ZeroMemory — это не хак а вполне корректный с точки зрения операционной системы способ зануления структуры используемой при системном вызове.
Не с точки зрения операционной системы, а в рамках конкретной платформы. В данном случае используется особенность платформы, состоящая в том, что примитивные типы данных имеют нулевое значение, представимое цепочкой нулевых байт.
Здравствуйте, Mr. None, Вы писали:
MN>Здравствуйте, Павел Кузнецов, Вы писали:
>>> Но человек задал вопрос, касающийся низкоуровневого кода, взаимодействующего с API операционной системы.
ПК>>Это твоя трактовка, не обязательно совпадающая с авторской.
MN>А кто сказал, что ваша трактовка совпадает с авторской? Автор не упомянул, что его интересуют способы зануления структур в общем виде, в том числе содержащих UDT и прочее, прочее, прочее... В вопросе автора фигурировали структуры и функции WinAPI — код который может появиться исключительно в модулях самого низкого уровня приложения для ОС Windows. В них и не пахнет ни UDT, ни конструкторами ни чем другим. При ответе же на его вопрос, вомнили всё — и связанное, и не связанное. Даже переносимость кода сюда приплели, хотя о какой переносимости кода может идти речь, когда в нём присуствует WNDCLASSEX и преславутая ZeroMemory... Если уж говорить о переносимости кода между различными компиляторами в рамках одной операционки (Windows), то вариант с ZeroMemory будет более переносим.
Самое смешное, что в этом ты абсолютно прав. Но это из серии -- исправляем дефекты реализации дефектами программмирования. Минус на минус...
>>> В таком коде фигурируют только POD-структуры, в таких случаях имеет право быть ZeroMemory или даже лучше memset — для переносимости. Для чего это надо? Хотя бы для таких хитрожопых компиляторов, которые в отличие от операцонной системы считают что null-pointer value это не 0.
ПК>>Как уже говорилось, если такой компилятор будет на такой операционке, то он как-нибудь должен будет делать соответствующие преобразования. И если ему вместо "логического" нуля подсунут "физический", полученный с помощью memset, то в ходе этих преобразований, "физический" ноль нулем быть перестанет. В случае же "обнуления" через = { 0 }, все отработает, как ожидалось, т.к. никаких сюрпризов для компилятора мы не создавали.
MN>В таком случае библиотека WinAPI тоже должна будет соответствующим образом портирована на такой компилятор и ZeroMemory должен будет работать так как и работал везде.
Ты, по-моему, всё никак не въедешь в фишку. Вот у тебя реализация. Запись
int x=int();
запишет в область памяти, оккупирванную x, некоторую последовательность байт -- платформенно зависимую. Значение x как целого числа при этом станет 0.
int x;
memset(&x,0,sizeof x);
запишет строго нулевую последовательность байт. Какое значение при этом получит x -- зависит от платформы.
Здравствуйте, Mr. None, Вы писали:
MN>Здравствуйте, Шахтер, Вы писали:
MN>>>Строго говоря функция ZeroMemory — это API-функция конкретной операционной системы и реализация компилятора тут не причём — это первое. MN>>>Второе — эта операционная система предполагает, что null-pointer value — это 0 (если быть совсем точным, то это все значения указателей, расположенных в диапазоне 0x00000000 — 0x0000FFFF). Поэтому если компилятор в качестве null-pointer value выбирает скажем 0xFFFFFFFF, любой вызов API-функции, ожадающей получение указателя проинициализированного значением null-pointer values, закончиться неудачей. Следовательно либо такой компилятор будет порождать неработоспособный код, либо надо как раз пользоваться функцией ZeroMemory, а не ={0}.
Ш>>Для обращения к функциям API придётся делать адаптеры, естественно. MN>Вот только если кто-нть обойдёт эти адаптеры — абзац выйдет... И кто в данном случае будет прав? Ведь мы не взирая на рекомендации производителя Visual Studio не использовать stl в своих проектах всё равно используем (кажись когда-то в MSDN-е было такое замечание, что stl поставляется только для совместимости с другим кодом и использовать её в новых проектах не рекоменуется).
MN>>>Инитересно, как в такой реализации будут интерпретироваться результаты вещественного типа, возвращаемые API-вызовами операционной системы? Или придётся ещё писать кучу функций типа float win32_float_to_this_magic_cpp_float(float)?
Ш>>Ага, именно так. MN>МАМА!! РОДИ МЕНЯ ОБРАТНО!!!!!
Что мешает автоматизировать этот процесс прогнав виндовые хидера через некоторый сильно упрощённый C-компилятор?
ПК>>>Как уже говорилось, если такой компилятор будет на такой операционке, то он как-нибудь должен будет делать соответствующие преобразования. И если ему вместо "логического" нуля подсунут "физический", полученный с помощью memset, то в ходе этих преобразований, "физический" ноль нулем быть перестанет. В случае же "обнуления" через = { 0 }, все отработает, как ожидалось, т.к. никаких сюрпризов для компилятора мы не создавали.
MN>>В таком случае библиотека WinAPI тоже должна будет соответствующим образом портирована на такой компилятор и ZeroMemory должен будет работать так как и работал везде.
Ш>Ты, по-моему, всё никак не въедешь в фишку. Вот у тебя реализация. Запись
Ш>
Ш>int x=int();
Ш>
Ш>запишет в область памяти, оккупирванную x, некоторую последовательность байт -- платформенно зависимую. Значение x как целого числа при этом станет 0.
Абсолютно согласен.
Ш>
Ш>int x;
Ш>memset(&x,0,sizeof x);
Ш>
Ш>запишет строго нулевую последовательность байт. Какое значение при этом получит x -- зависит от платформы.
И тут абсолютно согласен!
Я прекрасно понимаю, что memset(&x,0,sizeof(x)); забъёт участок памяти размером sizeof(x) начиная с &x нулями, но значение x при этом будет зависеть от платформы (компилятора). Ок, с первым вопросом разобрались .
Теперь переходим к следующему. Давайте представим на секунду реализацию компилятора для Win32, в которой нулевая последовательность байт не соответствует int(0). Точнее даже так int(0) представляет собой ненулевую последовательность байт. Внутри программы скомпилированной данным компилятором всё ок, но как только мы передаём такую переменную функции API всё рушиться, потому как она ожидает, что int(0) — это есть нулевая последовательность байт, поскольку она была скомпилирована другим компилятором.
Согласен — можно предположить, что подобный компилятор может позаботиться о преобразовании его int(0) в нулевую цепочку байт при передаче значения в функцию API. НО, сама Microsoft очень активно использует ZeroMemory для зануления структур в своих примерах и кодах из SDK и пр. и др. Я не думаю, что M$ пойдёт на поводу у разработчика такого компилятора и исправит все свои коды. Скорее это разработчик компилятора будет вынужден сделать так, чтобы структура занулённая с помощью ZeroMemory корректно передавалась в функции API. Таким образом имеем, в низкоуровневом коде, работающем с API вызовами WinAPI, мы смело можем использовать ZeroMemory — именно это я пытаюсь сказать вот уже вторые сутки.
Заметьте, я не утверждаю, что это правильно и только так и надо делать везде. Я только заявляю ещё раз это имеет право быть там, где это уместно — код низких уровней приложения.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Шахтер, Вы писали:
MN>>Использование ZeroMemory — это не хак а вполне корректный с точки зрения операционной системы способ зануления структуры используемой при системном вызове.
Ш>Не с точки зрения операционной системы, а в рамках конкретной платформы. В данном случае используется особенность платформы, состоящая в том, что примитивные типы данных имеют нулевое значение, представимое цепочкой нулевых байт.
И этой особенностью активно пользуются разработчики операционной системы Windows в своих исходниках, примерах, вспомогательных кодах из различных SDK. Поэтому можно предположить, что на любой платформе, на которой стоит ОС Windows ZeroMemory будет правильно занулять структуры из её API. Microsoft будет проще вставить соответствующую заплатку в операционку, чем переписать все свои сэмплы.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
> MN> Если уж говорить о переносимости кода между различными компиляторами в рамках одной операционки (Windows), то вариант с ZeroMemory будет более переносим. > > Самое смешное, что в этом ты абсолютно прав. Но это из серии -- исправляем дефекты реализации дефектами программмирования. Минус на минус...
Пример, пожалуйста. Я что-то ни одного не припомню, чтобы memset работал, а = { 0 } — нет.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
>>> Но человек задал вопрос, касающийся низкоуровневого кода, взаимодействующего с API операционной системы. > > ПК>Это твоя трактовка, не обязательно совпадающая с авторской. > > А кто сказал, что ваша трактовка совпадает с авторской? Автор не упомянул, что его интересуют способы зануления структур в общем виде, в том числе содержащих UDT и прочее, прочее, прочее...
Это называется более широкий взгляд на вопрос. Предотвращение неприятностей путем выработки хороших привычек. В самом деле, если для своих структур все равно нужно использовать = { 0 }, то зачем вообще оставлять использование ZeroMemory?
> В вопросе автора фигурировали структуры и функции WinAPI — код который может появиться исключительно в модулях самого низкого уровня приложения для ОС Windows.
Если низвести вопрос до уровня работы только с Win API — надо топать в соответствующий форум.
> Если уж говорить о переносимости кода между различными компиляторами в рамках одной операционки (Windows), то вариант с ZeroMemory будет более переносим.
Приведи конкретный пример, пожалуйста.
> В таком случае библиотека WinAPI тоже должна будет соответствующим образом портирована на такой компилятор и ZeroMemory должен будет работать так как и работал везде.
ZeroMemory и будет работать так же, как везде: будет обнулять переданный блок памяти.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
> Таким образом имеем, в низкоуровневом коде, работающем с API вызовами WinAPI, мы смело можем использовать ZeroMemory — именно это я пытаюсь сказать вот уже вторые сутки.
Уже вторые сутки тебе пытаются объяснить, что да, ты можешь использовать ZeroMemory при всех перечисленных ограничениях, но шаг влево, шаг вправо — и можно легко нарваться на неприятности. В результате возникает вопрос: зачем использовать ZeroMemory, если в общем случае есть лучшая альтернатива?
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Mr. None, Вы писали:
MN>Вот только если кто-нть обойдёт эти адаптеры — абзац выйдет... И кто в данном случае будет прав? Ведь мы не взирая на рекомендации производителя Visual Studio не использовать stl в своих проектах всё равно используем (кажись когда-то в MSDN-е было такое замечание, что stl поставляется только для совместимости с другим кодом и использовать её в новых проектах не рекоменуется).
Насколько я помню, речь там шла не об STL, а о старой библиотеке потоков.
А рекомендовалось использовать как раз STL :)
"Павел Кузнецов" <5834@news.rsdn.ru> wrote in message news:683866@news.rsdn.ru...
> Пример, пожалуйста. Я что-то ни одного не припомню, чтобы memset работал, а = { 0 } — нет.
Такое может случиться при инициализации объединений, первые члены которых имеют, например, плавающие типы.
>> Я что-то ни одного не припомню, чтобы memset работал, а = { 0 } — нет.
> Такое может случиться при инициализации объединений, первые члены которых имеют, например, плавающие типы.
Только в таком случае возникает вопрос: а какой из двух вариантов считать работающим? Кроме того, на платформе, где 0.0 или 0.0f представляется чем-то, отличным от последовательности нулевых байтов, memset для плавающих типов все равно использовать нельзя...
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Дарней, Вы писали:
Д>Признаюсь честно, привык писать обнуление структур в таком стиле:
Д> WNDCLASSEX wcx = { 0 };
Д>Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак Д>Интересно — может быть, есть какие-то аргументы против такой практики?
а если нужно будет обнуль структурку потом,
лучше уже сразу писать везде одинаково (ZeroMemory)
Здравствуйте, rsdn_avatara, Вы писали:
_>Здравствуйте, Дарней, Вы писали:
Д>>Признаюсь честно, привык писать обнуление структур в таком стиле:
Д>> WNDCLASSEX wcx = { 0 };
Д>>Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак Д>>Интересно — может быть, есть какие-то аргументы против такой практики?
а если нужно будет обнуль структурку потом,да и если сделаешь членом класса
лучше уже сразу писать везде одинаково (ZeroMemory)
всегда пытаюсь решать одну залачу одним методом
Здравствуйте, Павел Кузнецов, Вы писали:
>> В таком случае библиотека WinAPI тоже должна будет соответствующим образом портирована на такой компилятор и ZeroMemory должен будет работать так как и работал везде.
ПК>ZeroMemory и будет работать так же, как везде: будет обнулять переданный блок памяти.
И при передаче обнулённой таким образом структуры в любую функцию WinAPI все её атрибуты будут корректно трактованы как нулевые. Если это не будет исполняться, то все исходники и примеры поставляемые самой Microsoft, в которых ZeroMemory используется именно для этих целей перестанут работать. А таких очень много — в SDK только непосредственное упоминание ZeroMemory встречается в 150 cpp-файлах, а есть ещё десятка два макросов (типа RESET_THIS_MAGIC_STRUCT), в которых присутствует ZeroMemory. А ещё есть ATL и MFC и немеренное количество примеров из статей MSDN`а...
Или вы поможете Microsoft переписать все эти исходники?
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, Mr. None, Вы писали:
MN>>Вот только если кто-нть обойдёт эти адаптеры — абзац выйдет... И кто в данном случае будет прав? Ведь мы не взирая на рекомендации производителя Visual Studio не использовать stl в своих проектах всё равно используем (кажись когда-то в MSDN-е было такое замечание, что stl поставляется только для совместимости с другим кодом и использовать её в новых проектах не рекоменуется).
J>Насколько я помню, речь там шла не об STL, а о старой библиотеке потоков. J>А рекомендовалось использовать как раз STL
Кстати может быть... Можете точную цитату дать...
Я умею признавать свои ошибки, когда действительно неправ .
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Павел Кузнецов, Вы писали:
>> А кто сказал, что ваша трактовка совпадает с авторской? Автор не упомянул, что его интересуют способы зануления структур в общем виде, в том числе содержащих UDT и прочее, прочее, прочее...
ПК>Это называется более широкий взгляд на вопрос.
Более широкий взгляд на вопрос:
— Папа, откуда беруться дети?
— Ну, сынок, сначала были динозавры...
Шутка .
ПК>Предотвращение неприятностей путем выработки хороших привычек. В самом деле, если для своих структур все равно нужно использовать = { 0 }...
Если уж на то пошло, то для своих структур нужно использовать конструкторы...
ПК>то зачем вообще оставлять использование ZeroMemory?
1. Скажите пожалуйста, когда вы пишете под Windows, в частности код непосредственно контактирующий с API-вызовами, вы всегда используете только типы C++ (short int, long int) или иногда у вас проскакивают виндовые WORD и DWORD?
2. Для 64-битной платформы ZeroMemory уже объявлена не как макрос на memset, а как полноценная функция API (RtlZeroMemory) очевидно на это есть какие-то причины. Не удивлюсь, что вслед за этим выйдет "указ" Microsoft о том, чтобы ряд системных структур, например тех, память под которые выделяется в недрах ядра, обнулять только с её помощью.
>> В вопросе автора фигурировали структуры и функции WinAPI — код который может появиться исключительно в модулях самого низкого уровня приложения для ОС Windows.
ПК>Если низвести вопрос до уровня работы только с Win API — надо топать в соответствующий форум.
Как часто вы переносите вопросы касающиеся Win API, но попадающие сюда в соответствующий форум? Регулярно! Люди склонны ошибаться или их метод мышления в отношении структурирования данных может отличаться от вашего. А некоторые вопросы, как этот, вообще стоят на пограничных террирториях.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Блудов Павел, Вы писали:
БП>Здравствуйте, Mr. None, Вы писали:
MN>>Или вы поможете Microsoft переписать все эти исходники?
БП>Вот, пожалуйста, не приводите Microsoft как образчик хорошего кода. БП>Все, что живет в UserMode писано довольно дешевыми кодерами.
А я и не привожу... Стрелял бы всех этих программеров через одного...
Но факт остаётся фактом — большинство кода живёт уже второй десяток лет и регулярно пополняется новым, причём с теми же фишками (в частности использование ZeroMemory для зануления структур). В данном случае M$ сама попалась в свою ловушку монополиста — они обязаны будут поддерживать совместимость своего корявого кода, дабы не переписывать его заново, поэтому и нам беспокоиться нечего.
БП>Другое дело — ядро. Очень, очень качественная вещь. Линуксоидам БП>еще пахать и пахать, пока что-то лучшее получится.
БП>Так вот, поиск по DDK находит сплошь и рядом, как {0}, так и RtlZeroMemory.
так и RtlZeroMemory
Стало быть даже в ядре его используют...
БП>Вот в 2.6 Линуксе как-то не любят {0}. Наверное, есть все-таки кривые компиляторы, БП>на которых это не работает.
Именно об этом и сказал Аноним породив этот флейм
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
> ПК> для своих структур все равно нужно использовать = { 0 }... > > Если уж на то пошло, то для своих структур нужно использовать конструкторы...
Это далеко не всегда возможно. Например, структура, помещенная в union, не может иметь конструкторов. Есть и еще случаи, когда наделять структуру конструкторами просто нельзя.
> ПК>то зачем вообще оставлять использование ZeroMemory? > > 1. Скажите пожалуйста, когда вы пишете под Windows, в частности код непосредственно контактирующий с API-вызовами, вы всегда используете только типы C++ (short int, long int) или иногда у вас проскакивают виндовые WORD и DWORD?
Это к обсуждаемому вопросу никакого отношения не имеет — увод разговора в сторону.
> 2. Для 64-битной платформы ZeroMemory уже объявлена не как макрос на memset, а как полноценная функция API (RtlZeroMemory) очевидно на это есть какие-то причины. Не удивлюсь, что вслед за этим выйдет "указ" Microsoft о том, чтобы ряд системных структур, например тех, память под которые выделяется в недрах ядра, обнулять только с её помощью.
Снова "общефилософские" рассуждения о возможных вариантах развития будущего вместо четких технических аргументов. Впрочем, отвечу: не выйдет такого "указа". Иначе придется переписать очень много кода самой Windows, в котором — сюрприз? — = { 0 } вполне себе используется.
В общем, до появления новых технических, нефилософских, аргументов я свое участие в данной теме сворачиваю.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>От автора оригинального сообщения я подобных заявлений не слышал. Да и какой смысл в абстрактном "низкоуровневом обнулении куска памяти", если оно не означает обнуление всех элементов структуры?
Немного отвлекся от темы. Даже не ожидал, что тут такая дискуссия развернется
Хоть я и не говорил явно про "низкоуровневое обнуление", я имел в виду именно его. Предполагать, что такой подход будет использоваться для инициализации всех структур — это просто глупо.
Единственное применение для него (по крайней мере, в моих прогах) — это обнуление структур WinAPI (для того же используют обычно и ZeroMemory). В WinAPI очень много структур с кучей полей, и все они относятся к POD, поэтому применение такого подхода вполне правомерно, ИМХО. В любом случае — это намного лучше, чем инициализация случайными значениями. Забыл про одно поле — и всё, получил прогу с непредсказуемым поведением. Ищи потом, где что неправильно.
Написать же конструкторы в данном случае невозможно по вполне понятным причинам , и по этим же причинам можно не опасаться, что там появятся поля не-POD типов.
Здравствуйте, 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 ничего такого гарантировать не могут.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Лечение насморка отрубанием головы: зачем использовать кучу там, где можно обойтись выделением памяти "в стеке"?
Ну, может потребоваться, если блок чересчур велик для стека.
Здравствуйте, achp, Вы писали:
Д>>А вот ZeroMemory или memset ничего такого гарантировать не могут. A>Как это ничего? Они гарантируют, что нетипизированная область памяти (или массив объектов типа [un]signed] char) будет обнулена.
Дарней говорит про ЛОГИЧЕСКОЕ обнуление, а не физическое...
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
"Павел Кузнецов" <5834@news.rsdn.ru> wrote in message news:684083@news.rsdn.ru...
> >> Я что-то ни одного не припомню, чтобы memset работал, а = { 0 } — нет. > > > Такое может случиться при инициализации объединений, первые члены которых имеют, например, плавающие типы. > > Только в таком случае возникает вопрос: а какой из двух вариантов считать работающим? Кроме того, на платформе, где 0.0 или 0.0f представляется чем-то, отличным от последовательности нулевых байтов, memset для плавающих типов все равно использовать нельзя...
Считать работающим можно любой код вообще. Часто так и делают.
Оба варианта инициализации могут не работать. Все зависит от логики работы с инициализируемым объектом.
Для абстрактных данных в Си я предлагал следующее.
> ПК>От автора оригинального сообщения я подобных заявлений не слышал. Да и какой смысл в абстрактном "низкоуровневом обнулении куска памяти", если оно не означает обнуление всех элементов структуры?
> <...> Хоть я и не говорил явно про "низкоуровневое обнуление", я имел в виду именно его.
Ок. Если нужно побайтное обнуление — нужно использовать ZeroMemory/memset. Инициализация вида = { 0 } этого гарантировать не может. И наоборот, если нужна почленная инициализация значениями по умолчанию ("логический" 0) — нужно использовать что-нибудь из серии:
Struct s = { 0 };
Struct s = Struct();
и т.п.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, WolfHound, Вы писали:
Д>>>А вот ZeroMemory или memset ничего такого гарантировать не могут. A>>Как это ничего? Они гарантируют, что нетипизированная область памяти (или массив объектов типа [un]signed] char) будет обнулена. WH>Дарней говорит про ЛОГИЧЕСКОЕ обнуление, а не физическое...
Ага, я, читая его сообщение, проглядел слово "такого".
Здравствуйте, Павел Кузнецов, Вы писали:
>> Д> WNDCLASSEX wcx = { 0 };
>> а если нужно будет обнуль структурку потом,
ПК>
ПК>wcx = WNDCLASSEX();
ПК>
Тут ведь вот какая закавыка.
Насколько я понимаю, все эти выкрутасы используют положение стандарта о том, что для POD типов деволтный конструктор их "обнуляет". Но дело в том, что есть некомплиантые, но вполне еще используемые реализации компиляторов С++, где этого не делается.
Как-то привык все обнулять почленно/конструктором/мемсетом... Обязательно посмотрю, что бывает со структурой, инициализированной {0} в таком компиляторе.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ок. Если нужно побайтное обнуление — нужно использовать ZeroMemory/memset. Инициализация вида = { 0 } этого гарантировать не может. И наоборот, если нужна почленная инициализация значениями по умолчанию ("логический" 0) — нужно использовать что-нибудь из серии:
угу, для меня многое прояснилось.
Вроде бы такая простая вещь, а столько сложностей, оказывается
Здравствуйте, Аноним, Вы писали:
>>> Все что я сказал, это то, что участок памяти отведенной под структуру будет забит нулями! Все! ПК>>И каков смысл такого "обнуления"? А>Смысл в том, что для многих встроенных типов семантика такого обнуления равна семантике инициализации нулем. Вместого того, чтобы писать = 0; для кучи переменных типа int проще сразу забить всю структуру нулями а затем уже подкоректировать "некоторые оставшиеся" переменные, дав им нужные значения. Все! Это я и имел в виду!
Как-то встретился мне подобный код. Большой класс, в нем много переменных встроенных типов. Очень уж неохота было кому-то инициализировать каждую переменную по отдельности. И написал он такое:
some_class::some_class() {
ZeroMemory( this, sizeof( this ) );
}
Коротенький конструктор, три строчки, в файле из 10000 строк — не сразу заметишь. Понадобилось мне расширить этот класс. И вставил я в него переменную типа std::vector. Тут-то все и начилось. И вспомнил я того человека, кто такой конструктор написал, хорошим словом, после двух часов отладки...
Здравствуйте, alexkro, Вы писали:
A>Здравствуйте, Аноним, Вы писали:
>>>> Все что я сказал, это то, что участок памяти отведенной под структуру будет забит нулями! Все! ПК>>>И каков смысл такого "обнуления"? А>>Смысл в том, что для многих встроенных типов семантика такого обнуления равна семантике инициализации нулем. Вместого того, чтобы писать = 0; для кучи переменных типа int проще сразу забить всю структуру нулями а затем уже подкоректировать "некоторые оставшиеся" переменные, дав им нужные значения. Все! Это я и имел в виду!
A>Как-то встретился мне подобный код. Большой класс, в нем много переменных встроенных типов. Очень уж неохота было кому-то инициализировать каждую переменную по отдельности. И написал он такое: A>
A>some_class::some_class() {
A> ZeroMemory( this, sizeof( this ) );
A>}
A>
A>Коротенький конструктор, три строчки, в файле из 10000 строк — не сразу заметишь. Понадобилось мне расширить этот класс. И вставил я в него переменную типа std::vector. Тут-то все и начилось. И вспомнил я того человека, кто такой конструктор написал, хорошим словом, после двух часов отладки...
X>Тут ведь вот какая закавыка. X>Насколько я понимаю, все эти выкрутасы используют положение стандарта о том, что для POD типов деволтный конструктор их "обнуляет".
Не "деволтный конструктор их обнуляет", а выполняется инициализация по умолчанию, которая сводится к обнулению. Конструкторы тут в большинстве случаев ни при чем. Тем более, что у некоторых POD-типов вообще нет никаких конструкторов.
Здравствуйте, alexkro, Вы писали:
A>Коротенький конструктор, три строчки, в файле из 10000 строк — не сразу заметишь. Понадобилось мне расширить этот класс. И вставил я в него переменную типа std::vector. Тут-то все и начилось. И вспомнил я того человека, кто такой конструктор написал, хорошим словом, после двух часов отладки...
Здравствуйте, Дарней, Вы писали:
Д>Признаюсь честно, привык писать обнуление структур в таком стиле:
Д> WNDCLASSEX wcx = { 0 };
Д>Немного нагляднее и короче, чем ZeroMemory. Хоть это и небольшой хак Д>Интересно — может быть, есть какие-то аргументы против такой практики?
ZeroMemory — незаменимая вещь, если одна из структур наследует другую.
Т.е. бывает, что хочется расширить существующую структуру из POD элементов.
Можно написать копию + свои элементы, а можно наследоваться.
Если работать с C++, то "правильней", IMHO, это наследование.
После этого к расширенной таким образом структуре нельзя применять = {0}.
Во всех случаях, кроме вышеуказанного, я использую ={0}.
MShura:
> ZeroMemory — незаменимая вещь, если одна из структур наследует другую. <...> > После этого к расширенной таким образом структуре нельзя применять = {0}.
Есть три варианта кошерного "обнуления":
1) Не наследовать свою структуру, а включить в нее другую. В этом случае можно использовать = { 0 }.
2) Наследовать, но "обнулять" так:
MyStruct s = MyStruct();
3) Предоставить в унаследованной структуре конструктор, в котором и "обнулять" базовую структуру.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Андрей Тарасевич, Вы писали:
X>>Насколько я понимаю, все эти выкрутасы используют положение стандарта о том, что для POD типов деволтный конструктор их "обнуляет".
АТ>Не "деволтный конструктор их обнуляет", а выполняется инициализация по умолчанию, которая сводится к обнулению. Конструкторы тут в большинстве случаев ни при чем.
Да, незавимо от корректности построения фраз, выяснилось, что, даже в случае компилятора, который не выполняет иницализацию по умолчанию для POD типов, ={0} "обнуляет" (ну то есть выполняет инициализацию по умочанию) для входящих в структуру полей. И отказывается компилировать, если одно из полей или сама структура имеет конструктор.
АТ>Тем более, что у некоторых POD-типов вообще нет никаких конструкторов.
А что тогда для них вызывает какой-нибудь std::vector при вызове vector::vector(size_type)?
>> ZeroMemory — незаменимая вещь, если одна из структур наследует другую. <...> >> После этого к расширенной таким образом структуре нельзя применять = {0}.
ПК>Есть три варианта кошерного "обнуления":
ПК>2) Наследовать, но "обнулять" так: ПК>
ПК>MyStruct s = MyStruct();
ПК>
Не знаю что говорят об этом стандарты, но практика говорит, что ни VC6, ни VC7, ни gcc 3.2.2, ни Watcom 11 таким образом не "обнулят" структуру это точно.
MS>Не знаю что говорят об этом стандарты, но практика говорит, что ни VC6, ни VC7, ни gcc 3.2.2, ни Watcom 11 таким образом не "обнулят" структуру это точно.
Дааа, серьезные доводы против. Если уж Ватком не обнулит, то точно так не стоит делать
Of course, the code must be complete enough to compile and link.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
MS>>Не знаю что говорят об этом стандарты, но практика говорит, что ни VC6, ни VC7, ни gcc 3.2.2, ни Watcom 11 таким образом не "обнулят" структуру это точно.
L_L>Дааа, серьезные доводы против. Если уж Ватком не обнулит, то точно так не стоит делать
В недалеком прошлом у меня был очень большой опыт дизассемблирования программ.
Программу скомпилированную Watcom 10 и VC5 отличить можно было очень легко по генерируемому коду (не в пользу VC). Так что зря Вы так про Watcom.
К сожалению в настоящее время уже нет необходимости в частом дизассемблировании, поэтому сравнить кодогенераторы Watcom 11 с VC6/7 не могу. А специально исследовать этот вопрос мне не интересно.
Re[6]: ZeroMemory vs xxx = { 0 };
От:
Аноним
Дата:
24.06.04 12:50
Оценка:
X>А что тогда для них вызывает какой-нибудь std::vector при вызове vector::vector(size_type)?
Для них ничего не вызывается, для них, например, выполняется new(ptr)T(val); но это не есть вызов конструктора для встроенных типов (потому как нет никаких конструкторов встроенных типов)
Здравствуйте, Xentrax, Вы писали:
АТ>>Тем более, что у некоторых POD-типов вообще нет никаких конструкторов.
X>А что тогда для них вызывает какой-нибудь std::vector при вызове vector::vector(size_type)?
Ничего не вызывает. 'std::vector<T>' выполняет инициализацию своих элементов значением выражения 'T()'. Для типа 'int', например, значение этого выражения равно '0'. Просто само по себе равно '0'. Никаких конструкторов тут никак не замешано.
>>> ZeroMemory — незаменимая вещь, если одна из структур наследует другую. <...> >>> После этого к расширенной таким образом структуре нельзя применять = {0}.
ПК>>Есть три варианта кошерного "обнуления":
ПК>>2) Наследовать, но "обнулять" так: ПК>>
ПК>>MyStruct s = MyStruct();
ПК>>
MS>Не знаю что говорят об этом стандарты, но практика говорит, что ни VC6, ни VC7, ни gcc 3.2.2, ни Watcom 11 таким образом не "обнулят" структуру это точно.
VC6 — не обнулит, ибо это его известный глюк. VC7 — хм.. не знаю что там, но, насколько я слышал, это вопрос установок компиляции. GCC 3.x.x — не надо врать, обнулит без вопросов (это глюк пристутсвовал в GCC 2, не не в GCC 3). Не знаю, что там в Watcom 11...
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>Здравствуйте, MShura, Вы писали:
>>>> ZeroMemory — незаменимая вещь, если одна из структур наследует другую. <...> >>>> После этого к расширенной таким образом структуре нельзя применять = {0}.
ПК>>>Есть три варианта кошерного "обнуления":
ПК>>>2) Наследовать, но "обнулять" так: ПК>>>
ПК>>>MyStruct s = MyStruct();
ПК>>>
MS>>Не знаю что говорят об этом стандарты, но практика говорит, что ни VC6, ни VC7, ни gcc 3.2.2, ни Watcom 11 таким образом не "обнулят" структуру это точно.
АТ>VC6 — не обнулит, ибо это его известный глюк. VC7 — хм.. не знаю что там, но, насколько я слышал, это вопрос установок компиляции. GCC 3.x.x — не надо врать, обнулит без вопросов (это глюк пристутсвовал в GCC 2, не не в GCC 3). Не знаю, что там в Watcom 11...
Признаю свою ошибку по поводу gcc (не проверил версию, а приходится работать с разными).
Что касается VC7, то проверял на cl версии 13.10.3052 без каких-либо ключей.
> АТ>VC6 — не обнулит, ибо это его известный глюк. VC7 — хм.. не знаю что там, но, насколько я слышал, это вопрос установок компиляции. GCC 3.x.x — не надо врать, обнулит без вопросов (это глюк пристутсвовал в GCC 2, не не в GCC 3). Не знаю, что там в Watcom 11...
> Признаю свою ошибку по поводу gcc (не проверил версию, а приходится работать с разными). > Что касается VC7, то проверял на cl версии 13.10.3052 без каких-либо ключей.
Опять мимо. VC++ Toolkit 2003, на котором ты это по твоим словам проверял, так структуры обнуляет:
#include <iostream>
struct MyStruct
{
int i;
int j;
};
int main()
{
MyStruct s = MyStruct();
std::cout << s.i << ", " << s.j << std::endl;
}
C:\Prg\Microsoft\Visual C++ Toolkit 2003\bin>cl.exe -GX main.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3052 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.
main.cpp
Microsoft (R) Incremental Linker Version 7.10.3052
Copyright (C) Microsoft Corporation. All rights reserved.
/out:main.exe
main.obj
C:\Prg\Microsoft\Visual C++ Toolkit 2003\bin>main
0, 0
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Шахтер:
>> ЭЭЭ, Павел. Надо в обязательном порядке ассемблер проверять. А иначе это может быть случайностью.
ПК>Проверяй
Да не, всё правильно. С оптимизацией вообще зашибись -- без лишних телодвижений.
>> Что касается VC7, то проверял на cl версии 13.10.3052 без каких-либо ключей.
ПК>Опять мимо. VC++ Toolkit 2003, на котором ты это по твоим словам проверял, так структуры обнуляет: ПК>
Вообще-то речь шла об обнулении наследуемых структур.
Попробуйте вот этот вариант программы:
#include <iostream>
struct A{
int a;
};
struct B : public A{
int b;
};
int main()
{
B b = B();
std::cout << b.a << "," << b.b << std::endl;
return 0;
}
Здравствуйте, Аноним, Вы писали:
А>Лично мне такая запись не нравится по причине названной выше и очень не нравится, что Рихтер делает также (может заметили, что у него и другие ошибки есть?). Ричард Стивенс, чей уровень намного выше Рихтера никогда не позволяет себе так обнулять структуру — только через memset() и bzero() — и я также делаю как и он.