Является calloc (4, 6) тем же как calloc (6, 4)?

Правильный способ решить это с помощью lexer и синтаксического анализатора . Вы можете написать простые версии из них самостоятельно, или эти страницы также имеют ссылки на Java-лексеры и парсеры.

Создание рекурсивного синтаксического анализа является хорошим упражнением.

37
задан Ali 1 February 2009 в 23:49
поделиться

6 ответов

Это - то же. Причина состоит в том, потому что большую часть времени Вы хотите использовать sizeof оператор как один из аргументов. Если передача двух параметров беспокоит Вас, звонит malloc(), который имеет отдельный аргумент.

4
ответ дан Adrian Frühwirth 10 October 2019 в 09:13
поделиться

Люди главным образом используют подпрограммы распределения для выделения места для количества набора объектов, таким образом calloc() признает что быть указанным приятно. Так, например, если Вы хотите пространство для 100 целых чисел или 20 из Вашей собственной структуры:

int *pInt = calloc (100, sizeof(int));
tMyStruct *pMyStruct = calloc (20, sizeof(tMyStruct));

Этот код на самом деле выглядит немного "более хорошим", чем эквивалент malloc() вызовы:

int *pInt = malloc (100 * sizeof(int));
tMyStruct *pMyStruct = malloc (20 * sizeof(tMyStruct));

, хотя закаленным кодерам C нет никакого реального различия (кроме нулевой инициализации, конечно).

я должен сказать, что имею никогда , использовал calloc в дикой природе, так как я почти всегда создаю struct, где нуль не имеет смысла. Я предпочитаю инициализировать все поля вручную, чтобы гарантировать, чтобы я получил значения, которые я хочу.

22
ответ дан paxdiablo 10 October 2019 в 09:13
поделиться

calloc (4, 6) и calloc (6, 4) НЕ то же:

В типичной 32bit/64bit системе, первое выделило бы 32 байта и вторые 24 байта.

<час>
void *calloc(size_t nelem, size_t elsize);

ключевой пункт - то, что calloc должен возвратить память, как будто это было правильно выровненное как массив. Это предназначено, чтобы выделить массив и использоваться следующим образом:

A *p = (A*)calloc(count, sizeof(A));
for (int i = 0; i < count; ++i)
{
    f(&(p[i]));
    // f(p + i) is also valid
}

или

A *p = (A*)calloc(count, sizeof(A));
for (A *q = p; q != p + count; ++q)
{
    f(q);
}

calloc, как предполагается, выделяет дополнение принятия во внимание массива и другие эксплуатационные требования целевой системы. Таким образом на большей части машин на 32 бита, где 6 байтовых структур должны были бы быть дополнены к 8 байтам, они выделят 4 партии 8 байтов.

calloc, где первым аргументом является sizeof () наиболее вероятен ошибка и должен быть исследован.

calloc, где вторым аргументом не является sizeof (atype), не определен. Это сильно пахнет скрытыми предположениями и опасно для порта.

Разъяснение: В типичной 32bit/64bit системе, структура, вероятно, будет дополнена и выровнена к нескольким 32 битам. Как таковой в этих системах sizeof не был бы возврат 6 байтов. На самом деле нет никакой гарантии, что компилятор не заполнил бы и выровнял бы некоторым несколько 16 байтов если, именно это требует компилятор/платформа.

Мой ответ основан на факте, Вы не должны делать предположения о размере структуры. Они могут измениться с параметрами компилятора или целевой платформой. Просто удостоверьтесь, что Вашим вторым аргументом является sizeof выражение, и не делают посылки .

<час>

От стандарт :

calloc () функция должна выделить неиспользуемое место для массива nelem элементов, каждый чей размер в байтах является elsize. Пространство должно быть инициализировано ко всем битам 0.

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

9
ответ дан Pang 10 October 2019 в 09:13
поделиться

К превосходным отправленным ответам я хочу добавить еще одну точку расхождения между использованием calloc(nelem, elsize) по сравнению с malloc(nelem * elsize): качественные реализации calloc гарантируют, что, если Ваш nelem и elsize были достаточно большими для порождения целочисленного переполнения при умножении вместе это приведет к сбою, а не вызовет карликовое выделение как наивное malloc, вызов был бы.

Просто одна только эта функция была бы достаточно, чтобы я предпочел calloc malloc. Дополнительное чтение.

13
ответ дан Chris Jester-Young 10 October 2019 в 09:13
поделиться

Существует небольшое различие: Calloc может решить обнулить память только, поскольку он необходим и затем существует преимущество знания размера элементов.

я не могу назвать реализации, делающие это, но об этом думали для этого.

Как пример:

callocates 4 ГБ памяти, но система имеет только 2 ГБ: не имело бы смысла писать 2 ГБ нуля в виртуальную память, поэтому система могла установить грязный флаг на этой памяти для обнуления его, поскольку это загружается в память.

4
ответ дан Georg Schölly 10 October 2019 в 09:13
поделиться

Несмотря на принятый ответ (которому я верю, чтобы быть корректным), кажется, существуют беспорядки о том, сколько байтов выделяется из-за выравнивания. Таким образом, вот немного теста на моем 32-разрядном Linux с gcc-4.3:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  char* p1 = calloc(6, 4);
  char* p2 = calloc(4, 6);
  char* p3 = calloc(1,1);
  printf("%p, %p, %p\n", p1, p2, p3);
  return 0;
}

результат:

0x826b008, 0x826b028, 0x826b048

то, которое показывает, что и calloc(6,4) и calloc(4,6) выделяют тот же объем памяти, который является , округлилось к 32 байтам в моей системе. Изменение чисел к calloc(3,4) и calloc(4,3) даст следующий результат:

0x95d2008, 0x95d2018, 0x95d2028

, который показывает, что 16 байтов резервируются, когда 12 требуются и выделяются программе. В любом случае, и calloc(a,b) и calloc(b,a) вызовы имеют тот же эффект на использование памяти.

<час>

Добавленный Jonathan Leffler, потому что 300 символов никогда не будут достаточно.

Рассматривают эту программу, которая пропускает память как истинное решето, но демонстрирует точку:

#include <stdlib.h>
#include <stdio.h>

int main()
{
    int i, j, k;

    for (i = 1; i < 17; i++)
        for (j = 1; j < 9; j++)
            for (k = 0; k < 4; k++)
                printf("(%2d,%d)%d: %p\n", i, j, k, calloc(i, j));
    return(0);
}

В Windows, под Cygwin, это запускается путем выделения блоков, которые на расстоянии в 16 байтов (на самом деле, второй блок составляет 24 байта после первого, но после этого, они на расстоянии в 16 байтов). При выделении (2,7), адреса блока начинают увеличивать на 24 байта; аналогично, (3,4) выделяет блоки на расстоянии в 16 байтов, но (3,5) выделяет блоки на расстоянии в 24 байта. И, для записи оба (4,6) и (6,4) указатели возврата на расстоянии в 32 байта.

Это просто демонстрирует, что существуют немного служебные связаны с вызовом выделения. Если Вы смотрите на типичную реализацию malloc () и др. в K& R, Вы будете видеть, что размер блока хранится перед памятью, которую Вы наделены правом использовать. Различные реализации делают эти вещи по-другому; взволнованные по поводу растаптывающей памяти постараются не хранить управляющую информацию рядом, где пользователь может нанести ущерб.

, Когда Вы calloc (4,6), у Вас только есть надежный доступ к 24 байтам данных. Даже если Ваша реализация дает Вам возвращаемые значения, которые на расстоянии в 32 байта, Вы не можете безопасно больше использовать, чем 24 байта, которые Вы запросили. И отладочные версии malloc () будут наблюдать, пишете ли Вы из границ, Вы запросили.

5
ответ дан Chris Jester-Young 10 October 2019 в 09:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: