Как у malloc и calloc оказались разные подписи?

Возможный дубликат:
Почему calloc принимает два аргумента, а malloc - только один?

Существует множество ресурсов, описывающих разницу в функциональности между malloc и calloc, но я не могу легко найти тот, который описывает историю, лежащую за разными сигнатурами функций:

   void *calloc(size_t nmemb, size_t size);
   void *malloc(size_t size);

Конечно, size в первом является размером для каждого члена. Может быть, идея заключалась в том, что с помощью операционной системы можно было лениво сделать несколько часовых элементов размером с размер страницы?

(Я могу объяснить причины, а также следующий парень - нет принятых ответов без цитируемых источников.: -)

Ответ 1

Это несколько открыто для интерпретации языка, используемого в спецификации C.

Язык здесь кажется очень тщательно подобранным - malloc определен в разделе 7.20.3.3 следующим образом:

Функция malloc выделяет пространство для объекта, размер которого равен заданный по размеру и значение которого неопределенно.

Ранее объект был определен в разделе 3.14 следующим образом:

область хранения данных в среде исполнения, содержимое которых может представлять значения

calloc, с другой стороны, определен в 7.20.3.1 как:

Функция calloc выделяет пространство для массива объектов nmemb, каждый из которых имеет размер. Пробел инициализируется всеми битами нуль.

Это должно сделать это очевидным. Разница между calloc и malloc заключается в том, что calloc выделяет память для массива из n концептуальных объектов, хотя на практике это ничем не отличается от вызова malloc, который выделяет пространство для 1 концептуального объекта размера (n * size).

Итак, следующий вопрос: в чем необходимость разграничения пространства для массива объектов и пространства для одного большого объекта?

С точки зрения программистов два вызова функций просто требуют разных вещей. Один просит задать большой кусок памяти - и я буду заниматься этим. Другой говорит: мне нужен массив из n вещей такого размера, дайте мне некоторую память, которую я могу использовать для этого массива, и нуль - потому что в большинстве реализаций я могу сделать хорошие предположения о том, что означает обнуленная память.

Тот факт, что вы пытаетесь использовать его в качестве malloc + обнуления, является, по моему чтению спецификации, непониманием о цели функции.

У них были разные подписи, потому что они делали разные вещи.


Некоторые симпатичные побочные мысли... Тривиальная реализация malloc может выглядеть так:

#define malloc(x) (calloc(1, x))

Также интересно заметить, что если мое представление указателя NULL не обнулено, calloc не вернет мне массив указателей NULL. Еще лучше, если я создаю целочисленное представление, в котором обнуленная память отсутствует ((int) 0), calloc не вернет мне массив из 0s.