почему мы объявили массив int* в структуре что это значит?
Элемент array
используется для хранения содержимого стека. Однако мы не знаем заранее, сколько элементов должен содержать стек, поэтому мы не можем объявить его как обычный массив (чей размер должен быть известен во время компиляции1). Вместо этого мы будем выделять память во время выполнения с помощью библиотечной функции malloc
, которая возвращает указатель на первый элемент динамически выделяемого блока; этот указатель будет храниться в члене массива.
почему мы написали struct Stack * перед созданием функции
Поскольку функция createStack
возвращает указатель на новый экземпляр struct Stack
:
struct Stack *createStack( ... ) ----------------+
{ | The type of the expression in the
struct Stack *stack = ...; -----+ | `return` statement must match the
... | | return type of the function
return stack; <-----------------+---------------+
}
какая польза от неподписанного здесь
unsigned
— это сокращение от unsigned int
; это гарантирует, что для размера стека могут использоваться только неотрицательные значения.
Вот как выглядит память после вызова функции createStack
:
+---+
stack: | |----+ // The stack variable points to a struct Stack instance
+---+ |
... |
+---+ |
stack->top: | |<---+ // The actual struct Stack instance is created on the heap
+---+ // The -> operator allows us to refer to the members of the
stack->capacity: | | // instance through the stack pointer variable.
+---+
stack->array: | |----+ // The memory for the stack contents is allocated in a
+---+ | // separate malloc call, and the resulting pointer is
... | // stored in the instance's array member.
+---+ |
stack->array[0]: | |<---+
+---+
stack->array[1]: | |
+---+
stack->array[2]: | |
+---+
...
+---+
stack->array[N-1]: | | // N == stack->capacity
+---+
Переменная stack
в main
указывает на экземпляр struct Stack
; этот экземпляр создается строкой
struct Stack* stack = (struct Stack*) malloc(sizeof(struct Stack));
в функции createStack
. Память для экземпляра стека берется из «кучи» (области памяти, зарезервированной для динамического выделения). Внутри экземпляра стека член array
также указывает на область динамической памяти, зарезервированную другим вызовом malloc
:
stack->array = (int*) malloc(stack->capacity * sizeof(int));
Эта функция выделяет достаточно памяти для хранения столько объектов int
, сколько указано в элементе capacity
.
Изменить
Обратите внимание, что оба вызова malloc
можно очистить следующим образом:
struct Stack *stack = malloc( sizeof *stack );
...
stack->array = malloc( stack->capacity * sizeof *stack->array );
Если вы не используете компилятор C++ или компилятор C, предшествующий стандарту 1989 года, приведение типов не нужно (а в реализациях C89 опасно).
Выражения sizeof
используют разыменованное целевое выражение, а не имя типа; это немного убирает визуальный беспорядок и сокращает обслуживание, если вы когда-нибудь решите изменить тип целевой переменной (например, с int *
на double *
). Тип выражения *stack
— struct Stack
, поэтому следует, что sizeof *stack == sizeof (struct Stack)
. Точно так же тип выражения *stack->array
равен int
, поэтому sizeof *stack->array == sizeof (int)
. Обратите внимание, что круглые скобки требуются только в том случае, если операнд sizeof
является именем типа.
<ч> 1. C99 представил массивы переменной длины, размер которых может указываться во время выполнения, но они не будут работать в этом контексте по нескольким причинам.
person
John Bode
schedule
29.12.2014
c
типам данных. Есть много основных концептуальных проблем. - person Sourav Ghosh   schedule 29.12.2014int *
это не массив, это указатель. - person Iharob Al Asimi   schedule 29.12.2014