Я иду через ранее написанный код, и я нашел StringCbPrintf()
функция
Я нашел объявление на msdn
сайт, как это:
HRESULT StringCbPrintf(
_Out_ LPTSTR pszDest,
_In_ size_t cbDest,
_In_ LPCTSTR pszFormat,
_In_ ...
);
Что такое _in_
а также _out_
Вот ?
И зачем это нужно, когда у нас уже есть sprintf()
?
_In_
а также _Out_
(нота: ни _in_/_out
_ как вы написали, ни __In__/__Out__
с двойным подчеркиванием, как написано в другом ответе), так называемые SAL Аннотации. Их можно использовать с /analyze
опция компилятора, и может помочь выявить ошибки и проблемы, такие как переполнение буфера и т. д. с необработанными C-буферами и указателями. В дополнение к Документация MSDN по SAL, Вы также можете прочитать это Сообщение блога.
Кто-то по иронии судьбы (и превратно) написал что:
«В остальном мире входные данные являются постоянными указателями, но я думаю, что
было слишком просто. :)»
упустив тот факт, что SAL является более могущественный чем это. Фактически, с помощью SAL вы также можете указать максимальный размер буфера назначения, указывая, какой параметр содержит размер буфера назначения; например если вы откроете <strsafe.h>
заголовок, вы можете прочитать, что фактические аннотации SAL используются для StringCbPrintfW
(Unicode-версия StringCbPrintf
) как то так
STRSAFEAPI
StringCbPrintfW(
__out_bcount(cbDest) STRSAFE_LPWSTR pszDest,
__in size_t cbDest,
__in __format_string STRSAFE_LPCWSTR pszFormat,
...)
{
....
Обратите внимание, как __out_bcount(cbDest)
SAL аннотация применяется к pszDest
параметр указывает, что это указатель на выход буфер (__out
), который размер выражается в байтах (_bcount
) по параметру cbDest
, Как видите, это богатые аннотация (богаче простого «const
«или» не const
«).
На мой взгляд, SAL отчасти бесполезен, если вы пишете код на C ++ с такими надежными классами контейнеров, как std::vector
или же std::string
, которые знают свой собственный размер и т. д. Но SAL может быть полезен в коде C-ish с необработанными указателями (например, несколько Win32 API).
О второй части вашего вопроса:
«Зачем нам нужно
StringCbPrintf
если у нас уже естьsprintf
«
главная причина в том, что sprintf
является небезопасный и функция, склонная к переполнению буфера; вместо StringCbPrintf
Вы должны указать максимальный размер буфера назначения, и это может помочь предотвратить переполнение буфера (которые являются врагами безопасности).
Документация пытается объяснить, что для вас:
По сравнению с функциями, которые он заменяет, StringCbPrintf обеспечивает дополнительную обработку для
правильная обработка буфера в вашем коде. Плохая обработка буфера связана со многими проблемами безопасности, которые включают переполнение буфера. StringCbPrintf всегда завершается нулем с целевым буфером ненулевой длины.
__In__
а также __Out__
декораторы используются в Microsoft API: s для обозначения использования аргумента указателя. В остальном мире вклад const
указатели, но я думаю, это было слишком просто. 🙂
Как говорится Вот:
StringCbPrintf является заменой для следующих функций:
- sprintf, swprintf, _stprintf
- wsprintf
- wnsprintf
- _snprintf, _snwprintf, _sntprintf
Так что это не только заменить sprintf
но и те, с которыми можно работать wchar
, например. Он также вводит дополнительную обработку буфера для предотвращения переполнения буфера (как указано в той же статье msdn). Это также всегда null-завершает целевой буфер. _in_
а также _out_
там, чтобы показать вам, какие параметры являются входными, а какие выходными. Это наиболее вероятно #define
d как ничто, и уходи до начала компиляции.