c语言调用函数什么时候加'&'什么时候不加?

when should we add '&' and when we shouldn't while calling a function in c language?

程序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,假设已经创建了一个链接列表,其中 首先(声明为全局变量) 指向列表中的第一个节点。

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 函数时不使用。 create 和 display 函数都以指针作为参数。您能举例说明调用函数时 & 和 * 运算符之间的关系吗?提前致谢。

无论 x 的类型如何,&x 允许获得 x 的地址,无论目标是什么。如果需要获取 x 的值,请使用 x 如果需要获取其地址,请使用 &x

在第一个给出st地址的程序中允许create对其进行修改,所以在maincreate 返回变量 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 对来自 stcopy 起作用]main 并返回 main st

没有变化

做的时候

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

目标是读取一个 int 并将其记忆在字段 size 中,因为需要给出该字段的地址,所以 &st->size 而不是 st->size 给出它的值


在第二个程序中 first 已经是一个指针,这就是为什么 main 中的调用是 display(first); 而不是display(&first);,无论如何请注意 first 评估 NULL display 什么都不做,因为 (p!=NULL) 立即为 false

当然你也可以用 &first 得到 first 的地址但是在那种情况下你得到一个 struct Node ** 所以假设 display(&first); display必须改成void display(struct Node ** p)当然它的body也要适配

如果您想更改函数中的原始对象而不是其副本,则必须通过引用传递它。在 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;
}

然后函数将处理传递给函数的对象 st 的副本。更改副本对原始对象没有影响。

在第二个节目中

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 类型对象的副本。如果需要,您可以更改函数中的指向节点。

当您将一些 & 作为 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,因为发送 &stcreate() 可以让您访问存储 st 的内存。如果您发送 st——这只是存储位置的名称,st 的数据存储在该位置——作为 create() 的参数,这只是复制 ststruct Stack *st 并导致错误。并且您不能像 scanf("%d", &st->size); 那样使用其副本修改原始值,这就是为什么在第一个程序中您需要发送 st.

的地址的原因

程序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;
}

你已经有了struct Node类型的data所在的内存地址,即first的值。这就是为什么在这种情况下你不需要做 display(&first) 只需复制 first 并在 display() 函数中使用它。

Can you explain the relationship between & and * operator while calling a function with examples.

但是你也可以在程序B中做display(&first),像这样:

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;
}

我希望上面给出的示例能够清楚地说明在调用任何函数时根据其参数何时使用 *&。当心,使用 &firstdisplaying 数据会修改 *p=(*p)->next;first 的地址,并且您指向链表的 head 指针将会丢失,因此,这个例子仅用于演示目的。