繁体   English   中英

在C中将函数声明为变量

[英]Declaring functions as variables in c

我目前正在为我的大学准备考试,并且遇到了一些有关链接列表的令人困惑的代码示例。 在Steven S. Skiena撰写的《算法设计手册》中,他使用了一些我不太了解的有趣语法。

delete_list (list **l, item_type x)
{
    list *p;
    list *pred;
    list *search_list(), *predicessor_list();

    p = seach_list(*l, x);
    if (p != NULL)
    {
       pred = predecessor_list(*l, x);
       if (pred == NULL)
           *l = p-> next;
       else 
           pred->next = p->next;

       free (p);
    }

}

声明search_list()和predicessor_list()函数而不是显式调用它们是否有特定的优点或理由? 我假设它与维护指针有关,但是我在此上找不到任何参考资料。

这些是函数声明。 我认为有两件事对他们不利:

  1. 他们缺乏原型:

     list *search_list(list *, item_type), *predecessor_list(list *, item_type); 

    原型(此处为每个函数的list *, item_type )告诉编译器该函数期望什么类型的参数(以及多少个参数)。 没有理由不在函数声明中提供该信息。

    如果仅说list *search_list() ,则编译器无法检查search_list调用是否传递正确的参数。

  2. 它们在函数内部。

    在块内声明一个函数没有意义。 那不会使函数成为本地函数; 在标准C中,所有功能都是全局的。 它只是使声明具有局部作用域,这是毫无用处的。

一个更标准的方法是

list *search_list(list *, item_type);
list *predecessor_list(list *, item_type);

void delete_list (list **l, item_type x)
{
    ...
}

请注意,由于delete_list不返回任何值,因此添加了一个void返回类型。 省略1999 C之前版本允许的返回类型,但默认为int ,而不是void

鉴于函数原型在1989年ANSI C的发布中成为标准,并且在1999年删除了“ implicit int ”(使用ISO 9899:1999),因此,我对算法设计手册 (载于2008年)中的技术内容保持警惕版权声明)。

它们肯定是在某处声明的。示例:

#include <stdio.h>
#include <stdlib.h>

typedef struct list {

} list;

void foo() {
    //Forward Declaration:
    list* search_list(), *predecessor_list();

    //Function call:
    list* search_results = search_list(/*whatever arguments here*/);
    list* predecessor_results = predecessor_list(/*whatever arguments here*/);

    //Printing Pointers or whatever..
    printf("%p\n", search_results);
    printf("%p\n", predecessor_results);
}

list* search_list(/*whatever arguments here*/) {
    return NULL; //return a list pointer or node..
}

list* predecessor_list(/*whatever arguments here*/) {
    return NULL; //return a list pointer or node..
}

int main() {
    foo();
    return 0;
}

如果您注释掉:

/*list* search_list() {
    return malloc(sizeof(list));
}

list* predecessor_list() {
    return malloc(sizeof(list));
}*/

您将收到错误:

/ usr / bin / ld:/home/J3v1L7/cc02GJDL.o:在函数foo': prog.c:(.text+0x9): undefined reference to search_list的foo': prog.c:(.text+0x9): undefined reference to / usr / bin / ld:prog.c :(。 text + 0x13):未定义对`predecessor_list'的引用collect2:错误:ld返回1退出状态

为什么? 因为list* search_list(), *predecessor_list(); 是两个函数search_list和其predecessor的前向声明: https : search_list

list *search_list(), *predicessor_list(); 是2个函数的局部声明,这些函数采用未指定数量的参数并返回一个指针以list可能的内容。

在一个块范围声明函数是高度灰心。 在没有适当原型的情况下声明函数也是草率的。 定义没有返回类型的delete_list也是过时的。

从发布的代码来看,这本书似乎已经过时,并为新手提供了糟糕的建议。

正确的代码应为:

#include <stdlib.h>

typedef int item_type;

typedef struct list {
    item_type value;
    struct list *next;
} list;

list *search_list(list *l, item_type x);
list *predecessor_list(list *l, item_type x);

void delete_list(list **l, item_type x) {
    list *p;
    list *pred;

    p = search_list(*l, x);
    if (p != NULL) {
        pred = predecessor_list(*l, x);
        if (pred == NULL)
            *l = p->next;
        else 
            pred->next = p->next;
        free (p);
    }
}

当然,更好的delete_list版本可以避免双重扫描:

#include <stdlib.h>

/* delete the first node with value x, return 1 if found, else return 0 */
int delete_list(list **pp, item_type x) {
    for (list *p = *pp; p != NULL; pp = &p->next, p = p->next) {
        if (p->value == x) {
            *pp = p->next;
            free(p);
            return 1;
        }
    }
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM