Если у меня в качестве аргумента int ** a в моей функции Мне было интересно, в чем разница между a = (int **)malloc(sizeof(a)*(length) и *a = (int *)malloc(sizeof(a)*(length) Я обнаружил malloc на прошлой неделе, поэтому я пока не все понимаю. Спасибо !

0
Patrick Resal 21 Авг 2018 в 16:21

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;
2
hxpax 21 Авг 2018 в 14:03

В первом случае берется адрес памяти, выделенной при вызове malloc, и назначается его вашей переменной a. Второй берет адрес памяти, выделенной malloc, и сохраняет его в любой памяти, на которую a указывает.

Однако здесь есть еще один вопрос, который определяет, сколько памяти вы должны выделить. Если вы хотите, чтобы a сохранял массив указателей на целые числа, я бы использовал выражение a = (int**) malloc( length * sizeof(*a) );, которое проясняет, что вы выделяете пространство для ряда целочисленных указателей.

С другой стороны, если вы хотите выделить место для целого числа (не указателей) и уверены, что a указывает на переменную типа int*, используйте выражение {{X2 } }

Наконец, обратите внимание, что (по ссылке ниже в chux) нет необходимости и не рекомендуется приводить результат malloc(). Я оставил здесь в приведениях только для ясности, потому что они иллюстрируют, что мы храним возвращаемое значение в разных типах переменных в каждом случае.

1
Tim Randall 21 Авг 2018 в 13:49

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) память в обоих случаях может быть неправильной.

0
satyaGolladi 21 Авг 2018 в 13:52

Я думаю, что следующее ответит на ваш вопрос, но я не уверен на 100%. Давайте выясним!

Вы упоминаете «моя функция», что заставляет меня думать, что вы ссылаетесь не на свою основную функцию, а на то, что вы пишете функцию (возможно, для выделения a). Если это так, разница заключается в следующем; простая переменная int a в списке аргументов функции будет передана значением . Это означает, что если вы вызываете функцию, скажем, void foo(int x) с определенным значением, это значение будет скопировано в функцию. Поэтому, когда вы входите в функцию, вы не работаете с фактической переменной ; вместо этого вы работаете с копией. Где конкретная переменная существует, а где нет, называется область действия переменной .

Теперь к вашему практическому примеру: я предполагаю, что вы хотите разместить массив в функции. Если вы используете свой первый пример: a = (int **)malloc(sizeof(a)*(length) в функции, где a является аргументом, произойдет то же самое, что я описал выше. То есть a копируется в функцию, а затем вы размещаете ее там. Однако, когда ваша функция заканчивается, a уничтожается (обратите внимание: указатель, то есть память не освобождается правильно)! Если мое предположение верно, это, вероятно, не будет желаемым результатом.

По контракту, если ваша функция имеет int *a в качестве аргумента, аргумент будет передан по адресу. Теперь любые внесенные вами изменения (путем разыменования a с помощью оператора *) сохранятся даже после того, как вы вернетесь к месту, где была вызвана ваша функция.

-1
Floris 21 Авг 2018 в 13:57
51949703