Правильное выделение памяти для структуры

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

typedef struct string_collection {
    char **c;
    size_t current, allocated;
} TSC, *ASC;

Итак, я пришел с этим кодом, это правильно или я что-то пропустил? Сначала выделяется дескриптор структуры, а затем достаточно места для d указателей на строку

ASC AlocSC(size_t d)
{
    ASC sc;

    sc = (TSC*) malloc(sizeof(TSC));
    if (!sc) return NULL;

    sc->c = calloc(d, sizeof(char *));

    if (!sc->c) {
        free(sc);
        return NULL;
    }

    sc->current = 0;
    sc->allocated = d;

    return sc;
}

person Mike Egren    schedule 08.12.2011    source источник
comment
Являются ли «x» и «sc» одним и тем же?   -  person BRPocock    schedule 09.12.2011
comment
@MikeEgren: Ты забыл еще об одном x.   -  person AusCBloke    schedule 09.12.2011


Ответы (2)


Отредактированный код в основном правильный, хотя у меня есть несколько стилистических отличий от вас (например, отсутствие определения типа для сокрытия «указывания» объекта, неиспользование размера выделенного объекта в вызове malloc/calloc и несколько других вещей).

Ваш код немного «очистился»:

TSC *AlocSC(size_t d)
{
    TSC *sc = malloc(sizeof *sc);
    if (!sc) return NULL;

    sc->c = calloc(d, sizeof *sc->c);
    if (!sc->c) {
        free(sc);
        return NULL;
    }

    sc->current = 0;
    sc->allocated = d;

    return sc;
}
person Greg Jandl    schedule 08.12.2011
comment
Я думаю, что он был прав, на самом деле. Его элемент sc-›c — это char** - person BRPocock; 09.12.2011
comment
Почему sizeof(char), а не sizeof(char*)? - person Mike Egren; 09.12.2011
comment
@MikeEgren: Вы были правы, вам нужен массив указателей на строки, и это то, что вы выделили. - person AusCBloke; 09.12.2011
comment
Ач... упустил, что это char**; Я предполагал строку. Отредактирует ответ соответственно. - person Greg Jandl; 09.12.2011
comment
Если тип полностью непрозрачен (неполный в заголовке, используемом потребителем/программистом), то нет ничего плохого в сокрытии указателя. В остальном я полностью согласен. - person Jonathan Leffler; 09.12.2011
comment
@ Джонатан Леффлер - я согласен. Конечно, в этом случае вам также нужно приложить некоторые усилия, чтобы пользователь мог самостоятельно размещать экземпляры этого объекта. Одного размера недостаточно, так как он не учитывает требования выравнивания. - person Greg Jandl; 09.12.2011
comment
Обратите внимание, что использование calloc() для выделения массива указателей не гарантирует установку этих указателей в NULL. Язык не гарантирует, что нулевой указатель представлен как все биты-ноль. (Большинство компиляторов так и поступают, но полагаться на это не стоит.) Рекомендация: выделяйте массив указателей с помощью malloc() и не обращайтесь ни к одному из указателей, пока вы явно не присвоите им значение. - person Keith Thompson; 09.12.2011
comment
Поскольку компилятор может определить размер указателя на неполный тип, пользователю не обязательно знать размер; действительно, если пользователю необходимо знать размер структуры за непрозрачным типом, это не полностью непрозрачный тип. Однако это означает, что системе придется выделять память, что иногда может быть проблемой. - person Jonathan Leffler; 09.12.2011
comment
@Jonathan Leffler - звучит так, будто мы яростно соглашаемся - пока пользователь согласен с выделением объектов только в куче с помощью библиотечной функции, тогда, конечно, пользователю не нужно иметь какое-либо представление о размере объект. - person Greg Jandl; 09.12.2011

Пока x заменено на sc, мне кажется, все в порядке. Однако вам не следует возвращать malloc в C (подробнее читайте здесь ). Вместо этого я бы для этой строки:

sc = malloc(sizeof(*sc));

Вы можете сделать то же самое для размера типа x->c указывает на (char*).

person AusCBloke    schedule 08.12.2011
comment
и, как стилистический момент: если вы собираетесь определить «тип указателя», возможно, используйте его последовательно. Лично мне не нравятся определения типов указателей, поскольку я думаю, что они сбивают с толку других, читающих код; но еще более запутанно видеть, как используются TSC* и ASC; нужно вернуться к заголовочному файлу, чтобы обнаружить, что это одно и то же. - person BRPocock; 09.12.2011
comment
@BRPocock: Да, совершенно верно, меня раздражает наличие простых типов указателей typedef, но поскольку я убрал (TSC*), я подумал, что не буду использовать вместо этого (ASC). - person AusCBloke; 09.12.2011
comment
Это было больше направлено на оригинальный постер … в надежде, что я не буду поддерживать/редактировать/заменять еще одну программу, полную скрытых типов указателей. Мне достаточно трудно вспомнить мои -> и . разыменования с всеми подсказками */& в C… - person BRPocock; 09.12.2011