Традиционные библиотечные функции, стандартный memcpy
просто вызов функции. К сожалению, memcpy
часто вызывается для каждой маленькой копии, а накладные расходы на вызов функции, перетасовка нескольких байтов и возврат - это довольно много накладных расходов (особенно, поскольку memcpy
добавляет дополнительные вещи в начало функции для работы с неизмененной памятью, разворачивание цикла и т. д., чтобы преуспеть в копиях LARGE).
Итак, для компилятора для их оптимизации необходимо «знать», как это сделать, например, memcpy
- решение для этого состоит в том, чтобы в компилятор была встроена функция, которая содержит следующий код:
int generate_builtin_memcpy(expr arg1, expr arg2, expr size)
{
if (is_constant(size) && eval(size) < SOME_NUMBER)
{
... do magic inline memory copy ...
}
else
{
... call "real" memcpy ...
}
}
[для настраиваемых компиляторов, там, как правило, одна из этих функций для каждой архитектуры процессора, который имеет различные конфигурации, как в какие условия «реальные» memcpy
вызывается, или когда инлайн тетсру используется.]
Ключ здесь в том, что вы МОЖЕТЕ написать свой собственный memcpy
, который НЕ основан на __builtin_memcpy()
, который ВСЕГДА выполняет функцию и не делает то же самое, что и обычный memcpy
[у вас будет немного неприятностей, если вы измените его поведение много, поскольку стандартная библиотека C вероятно, звонит memcpy
в нескольких тысячах мест - но, например, делает статистику по тому, сколько раз вызывается memcpy
, и какие размеры могут быть копиями одного из таких прецедентов.
Другая важная причина для использования __builtin_*
заключается в том, что они предоставляют код, который в противном случае должен был бы быть написан на встроенном ассемблере или, возможно, вообще не доступен программисту. Настройка/получение специальных регистров будет такой.
Есть другие методы, чтобы решить эту проблему, например clang
имеет LibraryPass
, что предполагает библиотечные вызовы делают общие функции с другими альтернативами, например, так printf
гораздо «тяжелее», чем puts
, он заменяет соответствующие printf("constant string with no formatting\n")
S в puts("constant string with no formatting")
и многие тригонометрические и другие математические функции разрешаются в общих простых значений при вызове с константами и т.д.
Вызов __builtin_*
непосредственно для функций, таких как memcpy
или sin
или некоторые такие, вероятно, не то, чтобы сделать - это только делает ваш код менее портативны и вовсе не должны быть быстрее. Вызов __builtin_special_function
, когда нет другого, обычно является решением в некоторых сложных ситуациях - но вы, вероятно, должны обернуть его в свою собственную функцию, например.
int get_magic_property()
{
return __builtin_get_magic_property();
}
Таким образом, когда вы переносите в Windows, вы можете легко сделать:
int get_magic_property()
{
#if WIN32
return Win32GetMagicPropertyEx();
#else
return __builtin_magic_property();
#endif
}
Все, что с двумя последовательными символами подчеркивания или начиная с одного подчеркивания с последующим прописной буквы для реализации (система препроцессор, компилятор и компоновщик). Следовательно, вопрос должен быть связан с этим конкретным компилятором, а не с C++ вообще. –
Какой компилятор вы используете? – user763305
В большинстве случаев они бесполезны, и люди используют их по неверным причинам, воображая, что у них есть магические свойства. Если вы не используете '-fno-builtin-memcpy', gcc распознает, что memcpy является стандартной функцией и обрабатывает его так же, как __builtin_memcpy (что может просто излучать вызов функции libc memcpy). –