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


Автор: Rickert 29.10.2009, 05:49
Допустим есть:
Код
unsigned char* c = new unsigned char[256]

Я как-то всегда занулял:
Код
memset(c, 0, 256);

Есть ли какие-то специальные функции для именно зануления? Желательно стандартные, а не присуще одной системе/компилятору.

Автор: 586 29.10.2009, 06:55
Код
#include <algorithm>

unsigned char* c = new unsigned char[256];
std::fill(c, c+256, 0);

Автор: 586 29.10.2009, 07:11
Цитата(Rickert @  29.10.2009,  05:49 Найти цитируемый пост)
Есть ли какие-то специальные функции для именно зануления?

Компу без разницы, занулять, или нет, и то, что в функцию memset передаётся параметр для зануления не значит, что алгоритм зануления плохой.
Функция memset основана на ассемблерной инструкции rep stosd. И не важно, что будет находиться в регистре eax - нуль или не нуль.

Автор: Earnest 29.10.2009, 08:09
C другой стороны, неплохо помнить, что memset можно применять только к POD'ам, а std::fill к любым типам.

Автор: UnrealMan 29.10.2009, 15:21
Обычно это делается гораздо проще:

Код
unsigned char* c = new unsigned char[256]();

Если обнулять массив нужно не сразу после выделения памяти, то тогда хорошо подходит std::fill_n.

Автор: bsa 29.10.2009, 16:13
А еще лучше использовать std::vector<unsigned char>...

Автор: Rickert 30.10.2009, 02:10
Цитата(Earnest @  29.10.2009,  08:09 Найти цитируемый пост)
C другой стороны, неплохо помнить, что memset можно применять только к POD'ам, а std::fill к любым типам. 

Что такое POD?

Автор: dumb 30.10.2009, 03:39
Plain Old Data - по-русски говоря: простые типы, безо всякой "ООПщины".

Автор: Rickert 30.10.2009, 08:08
Всем спасибо!
solved smile 

Автор: Alexeis 30.10.2009, 10:21
Цитата(586 @  29.10.2009,  06:11 Найти цитируемый пост)
Функция memset основана на ассемблерной инструкции rep stosd. 

  Не факт smile . Это отдельная частная реализация. Запросто может вызываться функция оськи ZeroMemory.

Автор: Любитель 30.10.2009, 11:44
Цитата(Alexeis @  30.10.2009,  10:21 Найти цитируемый пост)
Запросто может вызываться функция оськи ZeroMemory. 

Эээ..
Из WinBase.h:
Код

#define ZeroMemory RtlZeroMemory

Из WinNT.h:
Код

#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))

Это не функция, это макрос smile

Автор: dumb 30.10.2009, 18:47
Цитата(Любитель @  30.10.2009,  11:44 Найти цитируемый пост)
Это не функция, это макрос
вообще говоря, такая функция присутствует и в kernel32.dll(в виде переходника) и в ntdll.dll. так что, если #define убрать(а в старых winnt.h он убирался какими-то #ifdef'ами), то будет вполне себе функция. smile

Автор: Любитель 30.10.2009, 19:01
Хм.. Не знал smile

Автор: Alexeis 30.10.2009, 19:13
RtlZeroMemory в ntdll.dll
RtlZeroMemory в kernel32.dll

Чет, мне казалось, что оська должна эффективней решать такие задачи как копирование / зануление / перемещение 

Автор: dumb 30.10.2009, 20:19
Цитата(Alexeis @  30.10.2009,  19:13 Найти цитируемый пост)
мне казалось, что оська должна эффективней решать такие задачи как копирование / зануление / перемещение

это все слишком элементарные операции, чтобы уповать на ОС в отношении эффективности их выполнения.

в случае использования функций из .dll получается слишком накладно использовать лишние push/call/ret - по временной стоимости эти операции многократно превышают(при среднестатистическом кол-ве перемещаемых/копируемых эл-тов) стоимость тех трех-четырех инструкций, которые собственно всю работу и делают. поэтому в release варианте эти "рабочие" инструкции просто вкрячиваются по месту вызова(инлайнятся).

Автор: Alexeis 30.10.2009, 21:11
Цитата(dumb @  30.10.2009,  19:19 Найти цитируемый пост)
это все слишком элементарные операции, чтобы уповать на ОС в отношении эффективности их выполнения.

  А вдруг кой чего может делаться аппаратно? Ведь x86 это не единственная платформа. При работе с графикой блоки могут быть больше мегабайта. Например контроллер DMA может кой чего делать и без процессора. Пока DMA будет выполнять операции с памятью, процессор может заняться вычислениями соседнего потока. Вот как стереть кадр не зануляя? Или же инициализировать массив POD типа большой длинны? Я видел реализации копирования памяти при помощи mmx регистров которые быстрее стандартных, аналогично можно себе представить здоровенный регистр SSE на 256 бит, который за один такт зануляет сразу 8 двойных слов. Это может получиться в разы быстрее. ОС знает архитектуру процессора, она может такие операции сделать гораздо быстрее и с меньшей нагрузкой на железо.

Автор: Любитель 30.10.2009, 22:39
Теоретически компилятор знает целевую архитектуру smile На практике - memset везде всё равно достаточно тупой.

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