когда мы должны добавлять '&', а когда не должны при вызове функции на языке c? - PullRequest
3 голосов
/ 13 июля 2020

Программа A

void create(struct Stack *st) 
{
    printf("Enter Size");
    scanf("%d",&st->size);
    st->top=-1;
    st->S=(int *)malloc(st->size*sizeof(int));
}

int main()
{
struct stack st;
create(&st);
return 0;
}

Программа B - для программы B предполагается, что связанный список был создан с первым (объявленным как глобальная переменная) , указывающим на 1-й узел в list.

struct Node 
{ 
 int data;
 struct Node *next;
}*first=NULL;

void display(struct Node *p) 
{
while(p!=NULL)
{
 printf("%d ",p->data);
 p=p->next;
}
} 

int main()
{
display(first);
return 0;
}

Я сомневаюсь, почему в программе A при вызове функции create требуется оператор & и почему в программе B его нет используется при вызове функции display . Обе функции создания и отображения принимают указатель в качестве аргумента. Можете ли вы объяснить связь между оператором & и * при вызове функции с примерами. Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 13 июля 2020

Когда вы отправляете & как arguments в любую функцию parameters, должно быть * для хранения этого & или, если есть * в parameters функции, вы можете отправить arguments например, & или *. Это простая связь.

В Программе A:

void create(struct Stack *st) 
{
    printf("Enter Size");
    scanf("%d",&st->size);
    st->top=-1;
    st->S=(int *)malloc(st->size*sizeof(int));
}

int main()
{
struct stack st;
create(&st);
return 0;

Вам нужно отправить &st, потому что отправка &st на create() предоставляет вам доступ к памяти, в которой хранится st. Если вы отправляете st - это просто имя ячейки памяти, где хранятся данные st - в качестве аргумента для create(), это будет просто копирование st в struct Stack *st и приведет к ошибке. И вы не можете изменить исходное значение, используя его копию, как в случае scanf("%d", &st->size);, поэтому в первой программе вам нужно отправить адрес st.

В Program B:

struct Node 
{ 
 int data;
 struct Node *next;
}*first=NULL;

void display(struct Node *p) 
{
while(p!=NULL)
{
 printf("%d ",p->data);
 p=p->next;
}
} 

int main()
{
display(first);
return 0;
}

У вас уже есть адрес памяти, где хранится data типа struct Node, то есть значение first. Вот почему вам не нужно делать display(&first) в этом случае, просто сделайте копию first и используйте ее в функции display().

Вы можете объяснить связь между & и * при вызове функции с примерами.

Но вы также можете сделать display(&first) в Программе B вот так:

struct Node 
{ 
 int data;
 struct Node *next;
}*first=NULL;

void display(struct Node **p) 
{
while(*p!=NULL)
{
 printf("%d ",(*p)->data);
 *p=(*p)->next;
}
} 

int main()
{
display(&first);
return 0;
}

и я надеюсь, что Пример, приведенный выше, поясняет, когда использовать * и & при вызове любой функции в соответствии с ее параметрами. Остерегайтесь, display обработка данных с использованием &first приведет к изменению адреса first в *p=(*p)->next;, и ваш head указатель на связанный список будет потерян, поэтому этот пример предназначен только для демонстрационных целей.

2 голосов
/ 13 июля 2020

Независимо от типа x &x позволяет получить адрес x независимо от цели. Если вам нужно получить значение x , используйте x, если вам нужно получить его адрес, используйте &x

В первой программе укажите адрес st позволяет create изменять его, поэтому в main back from create изменяется переменная st .

Но имея:

void create(struct Stack st) 
{
    printf("Enter Size");
    scanf("%d",&st.size);
    st.top=-1;
    st.S=(int *)malloc(st.size*sizeof(int));
}

int main()
{
  struct stack st;
  create(st);
  return 0;
}

в этом случае create работает с copy of st from main и обратно на main нет изменений в st

При выполнении

scanf("%d",&st->size);

цель состоит в том, чтобы прочитать int и запомнить его в поле size , для этого необходимо указать адрес этого поля, поэтому &st->size вместо st->size, которое дает его значение

Во второй программе first уже является указателем, поэтому вызов в main равен display(first);, а не display(&first);, в любом случае обратите внимание first оценка NULL display ничего не делает, потому что (p!=NULL) сразу ложно

Конечно, вы также можете получить адрес first с помощью &first, но в этом случае вы получите struct Node **, поэтому предположим, что display(&first); дисплей должен быть изменен на void display(struct Node ** p) и, конечно, его тело должно быть адаптировано

1 голос
/ 13 июля 2020

Если вы хотите изменить исходный объект в функции вместо его копии, вы должны передать его по ссылке. Передача по ссылке в C означает передачу объекта косвенно через указатель на объект.

Например, если в первой программе вы напишете

void create(struct Stack st) 
{
    printf("Enter Size");
    scanf("%d",&st.size);
    st.top=-1;
    st.S=(int *)malloc(st.size*sizeof(int));
}

int main()
{
struct stack st;
create(st);
return 0;
}

, тогда функция будет иметь дело с копия объекта, переданного в функцию. Изменение копии не влияет на исходный объект.

Во второй программе

struct Node 
{ 
 int data;
 struct Node *next;
}*first=NULL;

void display(struct Node *p) 
{
while(p!=NULL)
{
 printf("%d ",p->data);
 p=p->next;
}
} 

int main()
{
display(first);
return 0;
}

функция display работает с копией указателя first. Сам указатель в функции не изменяется. Так что передавать по ссылке смысла нет. С другой стороны, узел, на который указывает указатель, передается по ссылке. Таким образом, компилятор не создает копию объекта типа struct Node. Вы можете изменить заостренный узел в функции, если это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...