程序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中调用显示函数时不使用它。create和display函数都将指针作为参数。你能解释一下&和*运算符,同时调用带有示例的函数。提前谢谢。
当您将一些&
作为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
的地址。
在程序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;
}
我希望上面给出的例子能清楚地表明,在调用任何函数时,根据其参数,何时使用*
和&
。注意,使用&first
的display
ing数据会修改*p=(*p)->next;
中first
的地址,并且指向链表的head
指针将丢失,因此,此示例仅用于演示目的。
无论x&x
的类型允许获得x的地址,无论目标是什么。如果您需要获得x的值,请使用x
如果您需要获取其地址,则使用&x
在第一个给出st地址的程序中,允许create修改它,因此在main中,从reate返回变量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对st从main复制并返回main进行操作,st没有变化
进行时
scanf("%d",&st->size);
目标是读取int
并将其存储在字段size中,因此需要给出该字段的地址,因此&st->size
而不是st->size
,后者给出其值
在第二个程序中,第一个已经是一个指针,这就是为什么主中的调用是display(first);
而不是display(&first);
,无论如何,请注意值为NULL的第一次显示无效,因为(p!=NULL)
立即为假
当然,你也可以用&first
首先得到的地址,但在这种情况下,你得到的是struct Node **
,所以假设display(&first);
显示必须更改为void display(struct Node ** p)
,当然它的主体必须适应
如果要更改函数中的原始对象而不是其副本,则必须通过引用传递它。在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;
}
函数CCD_ 49处理指针CCD_。函数中没有更改指针本身。因此,通过引用传递它是没有意义的。另一方面,指针指向的节点是通过引用传递的。因此编译器不会创建structNode类型的对象的副本。如果需要,可以更改函数中的指向节点。