вы могли бы использовать exec
или eval
для выполнения кода python в виде строки. здесь здесь , здесь и здесь
calloc ()
инициализирует буфер нулями, в то время как malloc ()
оставляет память неинициализированной.
EDIT:
Обнуление памяти может займет немного времени, поэтому вы, вероятно, захотите использовать malloc ()
, если производительность является проблемой. Если инициализация памяти более важна, используйте calloc ()
. Например, calloc ()
может сохранить вам вызов memset ()
.
Менее известное различие заключается в том, что в операционных системах с оптимистичным распределением памяти, таких как Linux, указатель, возвращаемый malloc
, не поддерживается реальной памятью, пока программа не коснется это.
calloc
действительно касается памяти (записывает в нее нули), и, таким образом, вы можете быть уверены, что ОС поддерживает выделение фактической оперативной памятью (или подкачкой). По этой же причине он медленнее, чем malloc (он не только должен его обнулить, ОС также должна найти подходящую область памяти, возможно, заменив другие процессы)
См., Например, этот вопрос SO для дальнейшего обсуждения поведения malloc
Нет никакой разницы в размере выделенного блока памяти. calloc
просто заполняет блок памяти физическим шаблоном с нулевыми битами. На практике часто предполагается, что объекты, расположенные в блоке памяти, выделенном с помощью calloc
, имеют начальное значение, как если бы они были инициализированы литералом 0
, то есть целые числа должны иметь значение 0
, переменные с плавающей запятой - значение 0,0
, указатели - соответствующее значение нулевого указателя, и т. д.
Однако с педантичной точки зрения calloc
(а также memset (..., 0, ...)
) гарантированно только правильно инициализировать (нулями) объекты типа unsigned char
. Не гарантируется, что все остальное будет правильно инициализировано и может содержать так называемое представление ловушки , которое вызывает неопределенное поведение. Другими словами, для любого типа, отличного от unsigned char
, вышеупомянутый шаблон с нулевыми битами может представлять недопустимое значение, представление ловушки.
Позже, в одном из технических исправлений к стандарту C99, поведение было определено для всех целочисленных типов (что имеет смысл). То есть формально в текущем языке C можно инициализировать только целочисленные типы с помощью calloc
(и memset (..., 0, ...)
). Использование его для инициализации чего-либо еще в общем случае приводит к неопределенному поведению с точки зрения языка C.
На практике calloc
работает, как мы все знаем :), но если бы вы хотите использовать это (учитывая вышесказанное) зависит от вас. Я лично предпочитаю избегать этого полностью, вместо этого использую malloc
и выполняю свою собственную инициализацию.
Наконец, еще одна важная деталь заключается в том, что calloc
требуется для расчета окончательного размера блока ] внутренне , путем умножения размера элемента на количество элементов. При этом calloc
должен следить за возможным арифметическим переполнением. Это приведет к неудачному распределению (нулевой указатель), если запрошенный размер блока не может быть правильно рассчитан. Между тем, ваша версия malloc
не пытается следить за переполнением. В случае переполнения он выделит некоторый «непредсказуемый» объем памяти.
Одно часто упускаемое из виду преимущество calloc
заключается в том, что (соответствующие реализации) он помогает защитить вы против уязвимостей целочисленного переполнения. Сравните:
size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);
vs.
size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);
Первый может привести к крошечному выделению и последующим переполнениям буфера, если count
больше, чем SIZE_MAX / sizeof * bar
. Последний в этом случае автоматически выйдет из строя, так как объект такого размера не может быть создан.
Конечно, вам, возможно, придется следить за несовместимыми реализациями, которые просто игнорируют возможность переполнения ... Если это проблема на целевых платформах, вам все равно придется вручную проверить переполнение .