В C существует абстрактное понятие, формально известное как эффективный тип , означающее фактический тип данных, хранящихся в памяти.Это то, что компилятор отслеживает внутренне.
Большинство объектов в C имеют такой эффективный тип в момент объявления переменной, например, если мы введем int a;
, тогда эффективный тип того, что хранится вa
- это int
.
То есть допустимо совершать злые поступки, подобные этим:
int a;
double* d = (double*)&a;
*(int*)d = 1;
Это работает, потому что эффективный тип фактической памяти остается int
,хотя мы указали на это с дико несовместимым типом.Пока мы получаем доступ к тому же типу, что и эффективный тип, все хорошо.Если мы получим доступ к данным с использованием неправильного типа, произойдут очень плохие вещи, такие как программные сбои или неактивные ошибки.
Но когда мы вызываем malloc
семейство функций, мы только говорим им зарезервировать n
количество байтов, без указания типа.Эта память гарантированно будет размещена в соседних ячейках памяти, но не более того.Единственная разница между malloc
и calloc
состоит в том, что последний устанавливает все значения в этой необработанной памяти на ноль.Ни одна из функций не знает ничего о типах или массивах.
Возвращенный кусок сырой памяти не имеет эффективного типа.До того момента, когда мы получим к нему доступ, он получит эффективный тип, который соответствует типу, используемому для доступа.
Так же, как и в предыдущем примере, не имеет значения, какой тип указателя мы установилиуказать на данные.Не имеет значения, пишем ли мы int* i = malloc(n);
или bananas_t* b = malloc(n);
, потому что указанная память еще не имеет типа.Он не будет получен до тех пор, пока мы не получим к нему доступ в первый раз.