Зачем использовать bzero над memset?
в классе системного программирования, который я взял в этом предыдущем семестре, нам пришлось реализовать базовый клиент / сервер в C. При инициализации структур, таких как sock_addr_in
, или буферы символов (которые мы использовали для передачи данных между клиентом и сервером), профессор поручил нам использовать только bzero
, а не memset
для их инициализации. Он никогда не объяснял, почему, и мне любопытно, есть ли веская причина для этого?
Я вижу здесь: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown это bzero
более эффективно из-за того, что только когда-либо будет обнуление памяти, поэтому не нужно делать никаких дополнительных проверок, что memset
может сделать. Это все еще не обязательно похоже на причину абсолютно не использовать memset
для обнуления памяти.
bzero
считается устаревшим и, кроме того, не является стандартной функцией C. Согласно инструкции, memset
is предпочтительнее bzero
по этому поводу. Так почему же вы все еще хотите использовать bzero
над memset
? Просто для повышения эффективности, или это что-то большее? Аналогично, каковы преимущества memset
над bzero
что делает его де-факто предпочтительным вариантом для новых программ?
8 ответов
Я не вижу причин предпочесть bzero
над memset
.
memset
стандартная функция C при bzero
никогда не была стандартной функцией C. Обоснование, вероятно, потому, что вы можете достичь точно такой же функциональности, используя
Я предполагаю, что вы использовали (или ваш учитель повлиял) Сетевое программирование UNIX У. Ричард Стивенс. Он использует bzero
часто вместо memset
, даже в самой последней версии. Книга настолько популярна, я думаю, что она стала идиомой в сетевом программировании, поэтому вы все еще видите ее использование.
Я бы придерживался memset
просто так bzero
устарела и снижает мобильность. Я сомневаюсь, что вы увидите какие-либо реальные выгоды от использования one over другой.
единственное преимущество, которое я думаю bzero()
более memset()
Настройки Память до нуля, что есть меньше шансов на ошибку.
не раз я сталкивался с ошибкой, которая выглядела так:
memset(someobject, size_of_object, 0); // clear object
компилятор не будет жаловаться (хотя, возможно, некоторые уровни предупреждения могут быть на некоторых компиляторах), и эффект будет заключаться в том, что память не очищается. Потому что это не мусор объект - он просто оставляет его в покое - есть приличный возможно, ошибка не проявится в чем-то очевидном.
тот факт, что bzero()
Не стандарт является незначительным раздражителем. (FWIW, я не удивлюсь, если большинство вызовов функций в моих программах нестандартны; на самом деле написание таких функций-это моя работа).
в комментарии к другому ответу здесь Аарон Ньютон привел следующее из сетевого программирования Unix, Том 1, 3-е издание Стивенса и др. В разделе 1.2 (Курсив мой):
bzero
не функцию ANSI Си. Оно выведено от раннего Berkely сетевой код. Тем не менее, мы используем его во всем тексте, вместо этого из ANSI C
короче: memset
требуется больше сборочных операций, то bzero
.
Это источник: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown
Вы, наверное не стоит использовать bzero
, на самом деле это не стандартный C, это была вещь POSIX.
и обратите внимание, что слово "был" - это было устаревший в POSIX.1-2001 и удалены в POSIX.1-2008 из уважения к memset, поэтому вам лучше использовать стандартную функцию C.
хотел упомянуть что-то о аргументе bzero против memset. Установите ltrace, а затем сравните, что он делает под капотом.
На Linux с libc6 (2.19-0ubuntu6.6), сделанные вызовы точно такие же (через ltrace ./test123
):
long m[] = {0}; // generates a call to memset(0x7fffefa28238, '', 8)
int* p;
bzero(&p, 4); // generates a call to memset(0x7fffefa28230, '', 4)
мне сказали, что если я работаю в глубокие недра libc или любое количество интерфейса ядра / syscall, мне не нужно беспокоиться о них. Все, о чем я должен беспокоиться, это то, что вызов удовлетворяет требованию нуля буфер. Другие упоминали о том, какой из них предпочтительнее другого, поэтому я остановлюсь здесь.
для функции memset вторым аргументом является int
и третий аргумент size_t
,
void *memset(void *s, int c, size_t n);
обычно это unsigned int
, но если значения, как,0 and 16
для второго и третьего аргумента соответственно вводятся в неправильном порядке как 16 и 0 затем,
такой вызов memset все еще может работать, но ничего не сделает. Потому что количество байтов для инициализации указано как 0
.
void bzero(void *s, size_t n)
такой ошибки можно избежать, используя bzero, потому что замена двух аргументов на bzero всегда будет поймана компилятором C, если используются прототипы функций.
имейте это так, как вам нравится. :-)
#ifndef bzero
#define bzero(d,n) memset((d),0,(n))
#endif
внимание:
- оригинал
bzero
ничего не возвращает,memset
возвращает указатель void (d
). Это можно исправить, добавив typecast в void в определении. -
#ifndef bzero
не мешает вам скрывать исходную функцию, даже если она существует. Он проверяет существование макроса. Это может вызвать много путаницы. - невозможно создать указатель функции на макрос. При использовании
bzero
через указатели на функции, это не будет работать.