Понимание переменной со структурами и указателями в C

Я не знаю, что означает следующее приспособление:

struct reportItem * itemCopy = (struct reportItem *) malloc(sizeof(struct reportItem))

Может ли кто-нибудь объяснить шаг за шагом? Я действительно не знаю, что это значит.

Спасибо

Всего 3 ответа


struct reportItem - это тип структуры, который ранее был объявлен. Структура в C в основном представляет собой блок данных, который можно прочитать по частям, где каждая часть имеет тип и имя. Первая часть объявляет указатель itemCopy , который является просто переменной, хранящей адрес памяти. Функция struct reportItem просто сообщает компилятору, что данные на этом адресе памяти должны интерпретироваться как структура reportItem . malloc - это функция, которая выделяет память для хранения вещей. Вы рассказываете, сколько байт памяти вам нужно, и возвращает указатель, содержащий адрес первого байта этой недавно выделенной памяти. sizeof возвращает размер, в байтах, объекта или типа объекта. В этом случае он выделяет достаточно памяти для хранения одной структуры reportItem . Указатель, возвращаемый из malloc , затем отбрасывается к объявленному типу указателя, а itemCopy назначается для хранения этого адреса.


struct reportItem *itemCopy = (struct reportItem *) malloc(sizeof(struct reportItem));
//                            ^^^^^^^^^^^^^^^^^^^^^

Бросок не нужен и может скрыть ошибку, которую компилятор поймал бы в ее отсутствие (1)

struct reportItem *itemCopy = malloc(sizeof(struct reportItem));
//                                         ^^^^^^^^^^^^^^^^^^^

Использование самого типа здесь можно рассматривать как «случайное ожидание» (2). Безопаснее использовать сам объект

struct reportItem *itemCopy = malloc(sizeof *itemCopy);

Так что теперь это красивое заявление :)

Это вызывает библиотечную функцию malloc() (которая пытается зарезервировать область памяти для используемой программы) и присваивает полученное значение itemCopy .

Ответственность программиста - проверить, удалось ли malloc() зарезервировать память перед использованием этой памяти.

if (itemCopy == NULL) {
    //malloc failed to reserve memory
    fprintf(stderr, "no memory.
");
    exit(EXIT_FAILURE);
}

Кроме того, программист должен освободить память (обратно в ОС), как только эта память больше не требуется.

//use itemCopy
free(itemCopy);

(1) ошибка прикрытия

Если в области malloc() нет прототипа, компилятор предполагает, что он возвращает int . Затем, когда бросок молча преобразует этот незаконный int (незаконный, потому что это, по сути, значение void* ), указателю. Ошибка заключается в отсутствии #include <stdio.h> и приведения . Если вы просто удалите бросок, компилятор жалуется на преобразование из int в указатель. Если вы #include <stdio.h> и сохраните бросок, он будет лишним (и избыточным будет плохо).

(2) использование типа для определения объема памяти для распределения является «случайным ожиданием»

Вызов malloc(sizeof(struct whatever)) - это «случайное ожидание», потому что он заставляет программиста изменять код более чем в одном месте с одним изменением структуры.

Представим себе, что есть struct Car с некоторыми свойствами ... Позже было принято решение изменить часть кода на новую обновленную struct Vehicle (при сохранении активной struct Car ). Использование имени типа в вызове malloc() вызывает 2 изменения

struct Vehicle *x = malloc(sizeof (struct Vehicle));
//                                ^^^^^^^^^^^^^^^^ prevented accident

при использовании объекта требуется всего одно изменение

struct Vehicle *x = malloc(sizeof *x);
//                                ^^ *x is of the correct type 

sizeof (struct reportItem) возвращает размер, полученный с помощью типа struct structItem

malloc выделяет запрошенные байты в этом случае независимо от того, что возвращается sizeof (struct reportItem)

(struct reportItem *) используется для ввода значения, возвращаемого malloc. Однако это не требуется, вы можете проверить это для большего, нужно ли мне бросать malloc?

struct reportItem * ItemCopy затем назначает базовый адрес литой фиксированной памяти размера, полученного с помощью reportItem.


Есть идеи?

10000