Вы не можете объявить глобальные массивы в C, не указав им определенный числовой размер.Это потому, что глобальные переменные являются статическими, и компилятор не может выделять переменное количество памяти для глобального массива.
В C вы должны помнить, что массив на самом деле является просто указателем.Когда вы спрашиваете int *array = malloc(n * sizeof(int))
, вы говорите компилятору, что вам нужно n
много 4-байтовых блоков типа int, зарезервированных рядом в памяти, где значение array
фактически является указателем напервый 4-байтовый блок.
Когда вы обращаетесь к элементам массива, вы фактически делаете арифметику указателя и разыменовываете указатель, но это скрыто в синтаксисе array[i]
.Таким образом, когда массив имеет тип int, array[2]
переводится как переход в местоположение, указанное указателем массива (то есть головой), теперь перемещается на 2 * 4 байта в памяти и разыменовывает указатель для доступа к целому числу, хранящемуся там.
Так что, когда вы создаете двумерный массив, как вы уже обсуждали, лучшего способа сделать это не существует.Убедитесь, что у вас есть четкое представление о том, что на самом деле вы получаете от компилятора.Указатели (в любом случае на 64-битных машинах) - 8 байтов, а целые - 4 байта.Поэтому, когда вы вызываете int **M = malloc(sizeof(int*) * m
, компилятор выделяет вам m блоков шириной 8 байтов каждый, каждый из которых имеет тип int *.
Из других языков программирования кажется очень сложным объявить ссылку на указатель на блок указателей, но получение более высокого уровня представления о массиве и рассмотрение их как набора указателей действительно поможет вамв долгосрочной перспективе.Когда вам нужно передать эти типы данных между функциями, вам нужно иметь четкое представление о том, чем вы на самом деле манипулируете;указатель, значение, указатель на указатель?Это очень поможет вам в отладке кода этих идей, так как очень легко попытаться выполнить вычисления на указателях, а не на значениях.
3 Полезных советов:
calloc(n, sizeof(int))
может быть лучше, чем вызов malloc, поскольку calloc автоматически инициализирует ваши записи в ноль, а malloc - нет. - при вызове calloc / malloc вы хотите убедиться, что динамическое выделение памяти прошло успешно;если это не удастся, то malloc вернет NULL.
- Хорошее эмпирическое правило заключается в том, что каждый раз, когда вы вызываете malloc, вы хотите звонить бесплатно, как только закончите с памятью.Это может помочь предотвратить утечки памяти.