【问题标题】:when should we add '&' and when we shouldn't while calling a function in c language?在 c 语言中调用函数时,什么时候应该添加“&”,什么时候不应该添加?
【发布时间】:2020-11-02 15:00:59
【问题描述】:

程序 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,假设已创建一个链接列表,其中 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;
}

我的疑问是,为什么在程序 A 中调用 create 函数时,需要 & 运算符,为什么在程序 B 中调用 时不使用它显示功能。 create 和 display 函数都将指针作为参数。在调用函数时,您能举例说明 & 和 * 运算符之间的关系吗?提前致谢。

【问题讨论】:

  • 当您有一个变量并且需要将指向该类型变量的指针传递给函数时,您可以使用&。如果您已经有一个指向正确类型的指针,则不要使用&
  • &x 允许获取 x 的地址,无论其用途如何,如果您需要获取 x 的值,请使用 x if你需要得到它的地址使用&x
  • 在第二个程序中,传递的变量已经是一个指针。它被定义为*first
  • 当您将一些& 作为arguments 发送到任何函数的parameters 时,应该有* 来保存&。这只是关系。

标签: c pointers struct pass-by-reference pass-by-value


【解决方案1】:

当您将一些& 作为arguments 发送到任何函数的parameters 时,应该有* 来保存该&,或者如果函数的parameters 中有任何*,您可以发送@987654328 @ 喜欢&*。这只是关系。

程序 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的地址。

程序 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() 函数中使用它。

在调用函数时,你能举例说明 & 和 * 运算符的关系吗?

但您也可以像这样在程序 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;
}

我希望上面给出的示例清楚地说明何时根据参数调用任何函数时使用*&。注意,displaying data using &first会修改*p=(*p)->next;first的地址,你的head指向链表的指针会丢失,所以这个例子只是为了演示。

【讨论】:

    【解决方案2】:

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

    在第一个程序中给出st的地址允许create修改它,所以在main中从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;
    }
    

    在这种情况下,createmainstcopy 上工作,然后返回到 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),当然它的身体必须适应

    【讨论】:

      【解决方案3】:

      如果您想更改函数中的原始对象而不是其副本,则必须通过引用传递它。在 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 的副本。指针本身在函数中没有被改变。所以通过引用传递它是没有意义的。另一方面,指针指向的节点是通过引用传递的。所以编译器不会创建类型结构节点的对象的副本。如果需要,您可以更改函数中的指向节点。

      【讨论】:

      • 是的,我明白了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-30
      • 2020-07-16
      • 1970-01-01
      • 1970-01-01
      • 2010-10-18
      • 2023-04-02
      相关资源
      最近更新 更多