Почему в msvС++ у нас есть _snprintf, тогда как другие компиляторы позволяют snprintf

Что означает "_"? Почему Microsoft добавляет этот знак в начале?

Ответ 1

Идентификаторы в глобальном пространстве имен, начиная с _, зарезервированы для реализации. _snprintf - это просто функция, предоставленная реализацией (Visual Studio). Что касается обоснования этого, Visual Studio реализует C89, а snprintf является частью более позднего стандарта C99.

Кроме того, семантика обеих функций различна в обратном типе, который в snprintf всегда является числом символов, которые принимает форматированная строка (было ли достаточно свободного места в буфере или нет, а _snprintf будет возвращать отрицательное число, если в буфере недостаточно места.

То есть, чтобы выделить буфер, достаточно большой для вывода, который вы можете сделать:

int size = snprintf( 0, 0, "%s %d\n", str, i );
char * buffer = malloc( size+1 );
snprintf( buffer, size+1, "%s %d\n", str, i );

Вы не можете сделать это с помощью _snprintf, поскольку единственная информация, возвращаемая функцией, заключается в том, что текущего размера недостаточно.

Ответ 2

snprintf() еще не был частью стандарта на тот момент, когда среда выполнения Microsoft C начала поддерживать его.

Поскольку прототип функции не был стандартизован, и разработчики не хотели использовать имя snprintf (в случае, если стандарт позже указывал другой прототип), они решили добавить главное подчеркивание, чтобы обозначить функцию как Расширение Microsoft для стандарта.

Ответ 3

Добавление к приведенному выше,

существуют соответствующие C99 snprintf() и vsnprintf(), доступный с Visual Studio 2015

и они даже не запускают известное предупреждение о небрежном предупреждении функции.
_snprintf_s() или _vsnprintf_s(), при условии, являются "безопасными вариантами" функций, специфичных для MSVC, с поведением, отличным от C99.

Ответ 4

Помимо другого возвращаемого значения в случае недостаточно большого буфера (описанного в ответе Дэвида), функции из группы _sn... отличаются от стандартного snprintf в другом важном отношении. Если целевой буфер слишком короткий одним символом, функции _sn... считают эту ситуацию "успешной".

Более подробно, если целевой буфер достаточно длинный, чтобы сохранить всю результирующую последовательность, но без конечного нулевого символа, функции _sn... не обрезают результат, не записывают нулевой нуль в целевой буфер и возвращают размер буфера в результате. Таким образом, в общем случае результат не гарантируется с нулевым завершением.

В той же ситуации snprintf будет отбрасывать последний символ результирующей последовательности и записывать нулевой терминатор на свое место. Результат snprintf всегда заканчивается нулем.