Различные версии printf/scanf — невероятно медленные функции по следующим причинам:
Они используют списки переменных аргументов, что усложняет передачу параметров. Делается это с помощью различных непонятных макросов и указателей. Все аргументы должны быть проанализированы во время выполнения, чтобы определить их типы, что добавляет дополнительный служебный код. (Списки VA также довольно избыточная функция языка, а также опасная, поскольку она имеет гораздо более слабую типизацию, чем простая передача параметров.)
Они должны обрабатывать много сложного форматирования и поддерживать все различные типы. Это также увеличивает нагрузку на функцию. Поскольку все вычисления типов выполняются во время выполнения, компилятор не может оптимизировать части функции, которые никогда не используются. Поэтому, если вы хотите печатать только целые числа с помощью printf(), вы получите поддержку чисел с плавающей запятой, сложную арифметику, обработку строк и т. д. и т. д., связанную с вашей программой, как пустую трату места.
С другой стороны, такие функции, как strcpy() и особенно memcpy(), сильно оптимизированы компилятором и часто реализуются на встроенном ассемблере для максимальной производительности.
Некоторые измерения, которые я когда-то проводил на 16-битных младших микроконтроллерах barebone, приведены ниже.
Как правило, вы никогда не должны использовать stdio.h в любом виде производственного кода. Его следует рассматривать как библиотеку отладки/тестирования. MISRA-C:2004 запрещает использование stdio.h в производственном коде.
ИЗМЕНИТЬ
Заменил субъективные цифры фактами:
Измерения strcpy и sprintf на целевом Freescale HCS12, компилятор Freescale Codewarrior 5.1. Используя реализацию sprintf C90, C99 будет еще более неэффективным. Все оптимизации включены. Был протестирован следующий код:
const char str[] = "Hello, world";
char buf[100];
strcpy(buf, str);
sprintf(buf, "%s", str);
Время выполнения, включая перетасовку параметров при включении/выключении стека вызовов:
strcpy 43 instructions
sprintf 467 instructions
Выделенное место для программы/ПЗУ:
strcpy 56 bytes
sprintf 1488 bytes
Выделенное пространство ОЗУ/стека:
strcpy 0 bytes
sprintf 15 bytes
Количество вызовов внутренних функций:
strcpy 0
sprintf 9
Глубина стека вызовов функций:
strcpy 0 (inlined)
sprintf 3
person
Lundin
schedule
05.09.2012
snprintf
говорит вам, сколько символов было написано, и вам не нужно беспокоиться о пропущенных нулевых терминаторах, когда не хватает места. - person verdesmarald   schedule 05.09.2012strcpy()
только в том случае, если знаете длину исходной и целевой строк. Если вы знаете длину исходного кода, вы можете использоватьmemmove()
илиmemcpy()
вместоstrcpy()
. Обратите внимание, чтоstrncpy()
может быть очень неэффективным, если длина, указанная вами в качестве третьего аргумента, значительно превышает длину строки, потому чтоstrncpy()
null дополняет вывод до полной длины. И, как указывали другие,strncpy()
не гарантирует, что вывод завершается нулем. - person Jonathan Leffler   schedule 05.09.2012strncpy
может не добавлять завершающий символ'\0'
, заключается в том, что изначально он был создан для помещения текста в небольшие поля фиксированной длины, которые не нужно было завершать, если они были полностью заполнены. - person Some programmer dude   schedule 05.09.2012