Единственное преимущество, которое, как мне кажется, имеет bzero()
перед memset()
при установке памяти в ноль, состоит в том, что уменьшается вероятность ошибки.
Не раз сталкивался с ошибкой, которая выглядела так:
memset(someobject, size_of_object, 0); // clear object
Компилятор не будет жаловаться (хотя, возможно, на некоторых компиляторах могут возникнуть некоторые уровни предупреждений), и в результате память не будет очищена. Поскольку это не уничтожает объект - он просто оставляет его в покое - есть большая вероятность, что ошибка может не проявиться ни во чем очевидном.
Тот факт, что bzero()
не является стандартным, является незначительным раздражителем. (FWIW, я не удивлюсь, если большинство вызовов функций в моих программах нестандартны; на самом деле написание таких функций - это моя работа).
В комментарии к другому ответу здесь Аарон Ньютон процитировал следующее из Unix Network Programming, Volume 1, 3rd Edition, Stevens, et al., Section 1.2 (выделено мной):
bzero
не является функцией ANSI C. Он является производным от раннего сетевого кода Беркли. Тем не менее, мы используем его по всему тексту вместо функции ANSI C memset
, потому что bzero
легче запомнить (только с двумя аргументами), чем memset
(с тремя аргументами). Почти каждый поставщик, поддерживающий API сокетов, также предоставляет bzero
, а если нет, мы предоставляем определение макроса в нашем заголовке unp.h
.
Действительно, автор TCPv3 [TCP / IP Illustrated, Volume 3 - Stevens 1996] совершил ошибку, заменив второй и третий аргументы местами на memset
в 10 случаях при первой печати. Компилятор C не может отловить эту ошибку, потому что оба аргумента имеют один и тот же тип. (На самом деле, второй аргумент - это int
, а третий аргумент - это size_t
, что обычно является unsigned int
, но указанные значения 0 и 16, соответственно, все еще приемлемы для другого типа аргумента.) Вызов memset
по-прежнему работал , потому что только некоторые из функций сокета на самом деле требуют, чтобы последние 8 байтов структуры адреса Интернет-сокета были установлены в 0. Тем не менее, это была ошибка, и ее можно было избежать, используя bzero
, потому что замена двух аргументов на bzero
всегда будет перехвачен компилятором C, если используются прототипы функций.
Я также считаю, что подавляющее большинство вызовов memset()
обнуляются, так почему бы не использовать API, адаптированный к этому варианту использования?
Возможный недостаток bzero()
состоит в том, что компиляторы могут с большей вероятностью оптимизировать memcpy()
, потому что это стандартно, и поэтому они могут быть написаны для его распознавания. Однако имейте в виду, что правильный код все же лучше, чем неправильный код, который был оптимизирован. В большинстве случаев использование bzero()
не окажет заметного влияния на производительность вашей программы, и эта bzero()
может быть макросом или встроенной функцией, которая расширяется до memcpy()
.
person
Michael Burr
schedule
13.06.2013
memset
может быть немного менее эффективным из-за того, что выполняется немного больше проверок, определенно является случаем преждевременной оптимизации: какие бы выгоды вы ни увидели от пропуска одной или двух инструкций ЦП, они не стоят того, когда вы можете поставить под угрозу переносимость своего кода. .bzero
устарело, и это достаточная причина не использовать его. - person Sergey Kalinichenko   schedule 14.06.2013