Зачем использовать bzero над memset?
в классе системного программирования, который я взял в этом предыдущем семестре, нам пришлось реализовать базовый клиент / сервер в C. При инициализации структур, например sock_addr_in
, или char буферы (которые мы использовали для отправки данных между клиентом и сервером) профессор поручил нам использовать только bzero
, а не memset
для их инициализации. Он никогда не объяснял почему, и мне любопытно, есть ли для этого веская причина?
Я вижу здесь: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown это bzero
является более эффективным из-за того, что только когда-либо будет обнуление памяти, так что не нужно делать никаких дополнительных проверок, что memset
может сделать. Это все еще не обязательно кажется причиной абсолютно не использовать для обнуления памяти.
bzero
считается устаревшим и, кроме того, не является стандартной функцией C. Согласно инструкции, memset
is предпочтительнее, чем bzero
по этому поводу. Так почему же вы хотите по-прежнему использовать bzero
over memset
? Просто для повышения эффективности, или это что-то большее? Аналогично, каковы преимущества memset
over bzero
что делает его де-факто предпочтительным вариантом для новых программ?
8 ответов:
Я не вижу причин предпочесть
bzero
overmemset
.
memset
является стандартной функцией C в то время какbzero
никогда не было стандартной функции C. Обоснование, вероятно, потому, что вы можете достичь точно такой же функциональности с помощью
Я предполагаю, что вы использовали (или ваш учитель повлиял) UNIX Network Programming У. Ричард Стивенс. Он использует
bzero
часто вместоmemset
, даже в самом современном издании. Книга настолько популярна, я думаю, что она стала идиомой в сетевом программировании, поэтому вы все еще видите ее использование.Я бы придерживался
memset
просто такbzero
является устаревшим и снижает переносимость. Я сомневаюсь, что вы увидите какие-либо реальные выгоды от использования одного над другой.
единственное преимущество, которое я думаю
bzero()
болееmemset()
для установки памяти на ноль является то, что есть уменьшенная вероятность ошибки.не раз я сталкивался с ошибкой, которая выглядела так:
memset(someobject, size_of_object, 0); // clear object
компилятор не будет жаловаться (хотя, возможно, некоторые уровни предупреждений могут быть на некоторых компиляторах), и эффект будет заключаться в том, что память не очищается. Потому что это не мусор объект - он просто оставляет его в покое-есть приличный вероятность того, что ошибка может не проявиться во что-то очевидное.
дело в том, что
bzero()
не является стандартным является незначительным раздражителем. (FWIW, я не удивлюсь, если большинство вызовов функций в моих программах нестандартны; на самом деле написание таких функций-это моя работа).в комментарии к другому ответу здесь Аарон Ньютон привел следующее из сетевого программирования Unix, Том 1, 3-е издание Стивенса и др. В разделе 1.2 (Курсив мой):
bzero
не является функцией ANSI C. Его получают из раннего Беркли сетевой код. Тем не менее, мы используем его по всему тексту, вместо из 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
не мешает вам скрывать исходную функцию, даже если она существует. Он проверяет существование макроса. Это может вызвать много путаницы.- невозможно создать указатель функции на a макрос. При использовании
bzero
через указатели на функции, это не будет работать.