2013-01-05 70 views
5

在很多例子我读过一个简单的getListLength()函数会是这个样子:指针在C函数的参数

int getListLength(struct node *head) 
{ 
    struct node *temp = head; 
    int iCount = 0; 

    while (temp) 
    { 
     ++iCount; 
     temp = temp->next; 
    } 

    return iCount; 
} 

什么令我不需要的是一个本地指针的声明(在这种情况下* temp)复制传递的参数。如果我正确记得,传递的参数获得自己的副本。因此,不需要一个本地指针来复制*头部,因为*头部本身就是一个副本,对吧? 换句话说,放弃* temp指针并在所有地方使用head是否正确?

回答

4

是的,这是一个副本,所以是的,这将是正确的。

int getListLength(struct node* head) 
{ 
    int iCount = 0; 

    while (head) 
    { 
     ++iCount; 
     head = head->next; 
    } 
    return iCount; 
} 

你为什么不执行它并亲自看看?

4

确实,由于指针是按值传递的,所以不需要本地副本,但可能出于文体原因。有些人认为修改传入的参数是不好的形式(尽管我发现它在某些情况下很有用),但也许更重要的是,你丢失了代码中的一些自我文档;具体而言,head不再总是指向链表的真正头部。这并不是在你的短代码中引起混淆,但是当代码更长更复杂时,具有不准确的命名变量可能会更令人困惑。

+0

“代码更长更复杂时”。 - 我可以争辩。如果一个函数比发布的一个函数更长,并且它如此复杂以至于它完成多个任务并且需要记住变量名称,那么该函数应该可能被重构。 – 2013-01-05 21:19:05

+0

这可能是真的,但现实世界很少像人们想象的那样完美。 – jjlin

2

通常,为传入指针创建本地副本的原因是为了减少函数的side-effects(通过不修改函数参数)。

如果一个函数是只能使用指针读取(不写),并具有与外界没有其他互动,功能可以在GCC被标注为“纯”和将开放为了一些不错的优化。

例子:

__attribute__((pure)) int getListLength(struct node *head) 
{ 
    struct node *temp = head; 
    int iCount = 0; 

    while (temp) 
    { 
     ++iCount; 
     temp = temp->next; 
    } 

    return iCount; 
} 

如果你不熟悉什么副作用,尝试读取Side EffectsFunctional Programming维基百科文章,获得关于这个问题的更多信息。