void memset64( void * dest, uint64_t value, uintptr_t size )
{
uintptr_t i;
for( i = 0; i < (size & (~7)); i+=8 )
{
memcpy( ((char*)dest) + i, &value, 8 );
}
for( ; i < size; i++ )
{
((char*)dest)[i] = ((char*)&value)[i&7];
}
}
(Объяснение, согласно просьбе в комментариях: когда Вы присваиваете указателю, компилятор предполагает, что указатель выровненный к естественному выравниванию типа; для uint64_t, который составляет 8 байтов. memcpy () не делает такого предположения. На некоторых аппаратных средствах невыровненные доступы невозможны, таким образом, присвоение не является подходящим решением, если Вы не знаете невыровненную работу доступов над аппаратными средствами с маленьким или никаким штрафом, или знаете, что они никогда не будут происходить, или оба. Компилятор заменит маленький memcpy () s и memset () s с более подходящим кодом, таким образом, это не будет столь же ужасно, это взгляды; но если Вы действительно знаете достаточно, чтобы гарантировать, что присвоение будет всегда работать, и Ваш профилировщик говорит Вам, что это быстрее, можно заменить memcpy присвоением. Второе для () цикл присутствует в случае, если объем памяти, чтобы быть заполненным не является несколькими 64 битами. Если Вы знаете, что это всегда будет, можно просто отбросить тот цикл.)
Проверьте свою документацию ОС на локальную версию, затем рассмотрите просто использование цикла.
компилятор, вероятно, знает больше об оптимизации доступа к памяти на какой-то конкретной архитектуре, чем Вы, таким образом позвольте ему сделать работу.
Оборачивают его как библиотеку и компилируют его со всей оптимизацией улучшения скорости, которую позволяет компилятор.
Нет никакой стандартной библиотечной функции afaik. Таким образом, при написании портативного кода Вы смотрите на цикл.
, Если Вы пишете непортативный код затем, проверяют Ваш компилятор/документацию по платформе, но не задерживают дыхание, потому что редко получить много справки здесь. Возможно, кто-то еще войдет в долю с примерами платформ, которые действительно обеспечивают что-то.
способ, которым Вы записали бы свое собственное, зависит от того, можно ли определить в API, что вызывающая сторона гарантирует, что dst указатель будет достаточно выровненный для 64-разрядных записей на платформе (или платформах если портативен). На любой платформе, которая имеет 64-разрядный целый тип вообще, malloc, по крайней мере, возвратит соответственно выровненные указатели.
, Если необходимо справиться с неприсоединением, затем Вам нужно что-то как ответ moonshadow. Компилятор может встроить/развернуть это memcpy с размером 8 (и использовать 32-или 64-разрядная невыровненная операция в секунду записи, если они будут существовать), таким образом, код должен быть довольно холодным, но мое предположение - это, то вероятно, не будет особый случай целая функция для места назначения, бывшего выровненный. Я хотел бы быть исправленным, но бояться, что я не буду.
Поэтому, если Вы знаете, что вызывающая сторона будет всегда давать Вам dst с достаточным выравниванием для Вашей архитектуры и длину, которая является кратной 8 байтам, затем делайте записи простого цикла uint64_t (или независимо от того, что 64-разрядный интервал находится в Вашем компиляторе), и Вы будете, вероятно (никакие обещания) заканчиваются с более быстрым кодом. У Вас, конечно, будет более короткий код.
Независимо от того, что случай, если Вы действительно заботитесь о производительности затем, представляет ее. Если это не достаточно быстро, попробовали еще раз с большим количеством оптимизации. Если это все еще не достаточно быстро, задайте вопрос о asm версии для ЦП, на котором это не достаточно быстро. memcpy/memset может получить крупные увеличения производительности с оптимизации на платформу.
wmemset(3)
широкая (16-разрядная) версия memset. Я думаю, что это является самым близким, Вы собираетесь войти в C без цикла.
Необходимо действительно позволить компилятору оптимизировать это для Вас, как кто-то еще предположил. В большинстве случаев тот цикл будет незначителен.
, Но если эта некоторая специальная ситуация и Вы не возражаете быть конкретной платформой, и действительно должны избавиться от цикла, можно сделать это в блоке блока.
//pseudo code
asm
{
rep stosq ...
}
можно, вероятно, погуглить stosq команду блока для специфических особенностей. Это не должны быть больше, чем несколько строк кода.
запишите свое собственное; это тривиально даже в asm.