Кажется, есть фундаментальное недоразумение.
malloc (sizeof (struct a) * n) выделяет n номеров типа struct a.
Нет, это именно то, что обычно используют, как после такого звонка. malloc(size)
выделяет область памяти размером size
байт. То, что вы делаете с этим регионом, полностью зависит от вас. Единственное, что имеет значение, это то, что вы не выходите за пределы выделенной памяти. Предполагая 4 байта float
и int
и 8 байтов double
, после успешного malloc(100*sizeof(float));
вы можете использовать первые 120 из 400 байтов в качестве массива 15 double
с, следующие 120 в качестве массива 30 float
с, затем поместите массив из 20 char
с сразу за этим и заполните оставшиеся 140 байтов 35 int
с, если хотите. Это совершенно безобидное определенное поведение.
malloc
возвращает void*
, который может быть неявно приведен к указателю любого типа, поэтому
some_type **array = malloc(100 * sizeof(data *)); // intentionally unrelated types
совершенно нормально, это может быть не тот объем памяти, который вы хотели. В этом случае это очень вероятно, потому что указатели имеют одинаковый размер независимо от того, на что они указывают.
Скорее всего, неправильный объем памяти будет
data *array = malloc(n * sizeof(data*));
как у тебя было. Если вы используете выделенный фрагмент памяти в качестве массива n
элементов типа data
, существует три варианта
sizeof(data) < sizeof(data*)
. Тогда ваша единственная проблема в том, что вы тратите немного места.
sizeof(data) == sizeof(data*)
. Все в порядке, места не теряется, как будто у вас вообще не было опечаток.
sizeof(data) > sizeof(data*)
. Затем вы получите доступ к памяти, к которой вы не должны были обращаться при прикосновении к последующим элементам массива, что является неопределенным поведением. В зависимости от различных вещей, которые могли бы последовательно работать, как если бы ваш код был корректным, немедленно приводить к аварийному завершению работы с сегфоутом или чем-то промежуточным (технически это могло бы вести себя так, что не может быть разумно помещено между этими двумя, но это было бы необычно). 1041 *
Если вы намеренно делаете это, зная, что применяются пункты 1. или 2., это плохо практика, но не ошибка. Если вы делаете это непреднамеренно, это ошибка независимо от того, какой пункт применяется, безвредный, но трудно найти, когда применяется 1. или 2., вредный, но обычно легче обнаружить в случае 3.
В твоих примерах. data
было 4 соотв. 8 байтов (вероятно), что в 64-битной системе помещает их в 1. соотв. 2. с большой вероятностью в 32-битной системе на 2 соотв. 3.
Рекомендуемый способ избежать таких ошибок -
type *pointer = malloc(num_elems * sizeof(*pointer));