Если у меня в качестве аргумента int ** a в моей функции Мне было интересно, в чем разница между a = (int **)malloc(sizeof(a)*(length)
и *a = (int *)malloc(sizeof(a)*(length)
Я обнаружил malloc на прошлой неделе, поэтому я пока не все понимаю. Спасибо !
4 ответа
malloc
просто возвращает указатель void *
, не более того.
a
является указателем на указатель.
Правая сторона знака равенства здесь не важна, поэтому оставьте правую сторону в покое. Теперь мы получили:
// 1st code fragment
int **a1;
// Asign a null pointer to a1, now a1 is a NULL pointer
a1 = (int **)NULL;
// 2rd code fragment
int **a2;
// Asign a null pointer to the pointer pointed by a2.
// Here may crash actually, because a2 is not initialized yet.
*a2 = (int *)NULL;
В первом случае берется адрес памяти, выделенной при вызове malloc
, и назначается его вашей переменной a
. Второй берет адрес памяти, выделенной malloc
, и сохраняет его в любой памяти, на которую a
указывает.
Однако здесь есть еще один вопрос, который определяет, сколько памяти вы должны выделить. Если вы хотите, чтобы a
сохранял массив указателей на целые числа, я бы использовал выражение a = (int**) malloc( length * sizeof(*a) );
, которое проясняет, что вы выделяете пространство для ряда целочисленных указателей.
С другой стороны, если вы хотите выделить место для целого числа (не указателей) и уверены, что a
указывает на переменную типа int*
, используйте выражение {{X2 } }
Наконец, обратите внимание, что (по ссылке ниже в chux) нет необходимости и не рекомендуется приводить результат malloc()
. Я оставил здесь в приведениях только для ясности, потому что они иллюстрируют, что мы храним возвращаемое значение в разных типах переменных в каждом случае.
int ** a;
a
имеет тип целочисленного двойного указателя.
a = (int **) malloc (sizeof (a) * (length));
Неинициализированная память размером sizeof(a)*(length)
, выделенная a
при успешном выполнении malloc.
* a = (int ) malloc (sizeof (a) (length);
Неинициализированная память размером sizeof(a)*(length)
, выделенная a[0]
(если инициализируется только в противном случае, происходит сбой) при успешном выполнении malloc.
Примечание: sizeof (a) - это размер двойного указателя, это 4 байта для 32-битной машины. Так что выделение одна и та же память, т.е. sizeof(a)*(length)
память в обоих случаях может быть неправильной.
Я думаю, что следующее ответит на ваш вопрос, но я не уверен на 100%. Давайте выясним!
Вы упоминаете «моя функция», что заставляет меня думать, что вы ссылаетесь не на свою основную функцию, а на то, что вы пишете функцию (возможно, для выделения a). Если это так, разница заключается в следующем; простая переменная int a
в списке аргументов функции будет передана значением . Это означает, что если вы вызываете функцию, скажем, void foo(int x)
с определенным значением, это значение будет скопировано в функцию. Поэтому, когда вы входите в функцию, вы не работаете с фактической переменной ; вместо этого вы работаете с копией. Где конкретная переменная существует, а где нет, называется область действия переменной .
Теперь к вашему практическому примеру: я предполагаю, что вы хотите разместить массив в функции. Если вы используете свой первый пример: a = (int **)malloc(sizeof(a)*(length)
в функции, где a
является аргументом, произойдет то же самое, что я описал выше. То есть a
копируется в функцию, а затем вы размещаете ее там. Однако, когда ваша функция заканчивается, a
уничтожается (обратите внимание: указатель, то есть память не освобождается правильно)! Если мое предположение верно, это, вероятно, не будет желаемым результатом.
По контракту, если ваша функция имеет int *a
в качестве аргумента, аргумент будет передан по адресу. Теперь любые внесенные вами изменения (путем разыменования a
с помощью оператора *
) сохранятся даже после того, как вы вернетесь к месту, где была вызвана ваша функция.
Связанные вопросы
Новые вопросы
c
C - это язык программирования общего назначения, используемый для системного программирования (ОС и встраиваемых), библиотек, игр и кроссплатформенности. Этот тег следует использовать с общими вопросами, касающимися языка C, как это определено в стандарте ISO 9899 (последняя версия 9899: 2018, если не указано иное, а также для запросов, специфичных для версии, с c89, c99, c11 и т. Д.). C отличается от C ++ и не должен сочетаться с тэгом C ++ без разумной причины.