Зачем использовать 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 ответов:
Я не вижу причин предпочесть
bzeroovermemset.
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через указатели на функции, это не будет работать.