使用 C 在双向链表中隐式声明函数
Implicit declaration of function in doubly linked list using C
这不是程序的最终实现,但程序本身有点长,所以我决定改为将其分成小块来创建。我 运行 遇到一个错误
implicit declaration of function list_first.
还有其他错误需要解决,但我想先得到一些帮助,然后再自己解决其余的问题,尽管如果您愿意,欢迎您提供额外的帮助。这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// The type for a node in the list.
struct node
{
struct node *next;
struct node *prev;
char *value;
};
// The type for a list.
typedef struct list
{
struct node head;
} List;
// The type for a list position.
typedef struct list_pos
{
struct node *node;
} ListPos;
List *list_create(void)
{
List *lst = (List*)malloc(sizeof(List));
if(lst == NULL)
{
printf("No more memory!\n");
}
return lst;
}
static struct node *make_node(const char *value)
{
struct node *result = malloc(sizeof(struct node));
result->value = strdup(value);
result -> next = NULL;
result -> prev = NULL;
return result;
}
static void add_values(List *lst)
{
ListPos pos = list_first(lst);
pos = list_insert(pos, "Apple");
pos = list_next(pos);
pos = list_insert(pos, "Banana");
pos = list_next(pos);
pos = list_insert(pos, "Citrus");
}
ListPos list_end(List *lst)
{
ListPos pos = {
.node = &lst->head
};
return pos;
}
ListPos list_first(List *lst)
{
ListPos pos = {
.node = lst->head.next
};
return pos;
}
ListPos list_next(ListPos pos)
{
struct node* node;
//pos = node -> next;
struct node *before = pos.node->prev;
struct node *after = pos.node;
node->next = after;
after->prev = node;
pos.node = node;
return pos;
}
ListPos list_insert(ListPos pos, const char *value)
{
// Create a new node.
struct node *node = make_node(value);
// Find nodes before and after (may be the same node: the head of the list).
struct node *before = pos.node->prev;
struct node *after = pos.node;
// Link to node after.
node->next = after;
after->prev = node;
// Link to node before.
node->prev = before;
before->next = node;
// Return the position of the new element.
pos.node = node;
return pos;
}
int main(void)
{
// Create an empty list.
List *lst = list_create();
add_values(lst);
return 0;
}
在使用函数的行之前必须是函数的原型或函数定义本身。在函数和您指定的其他函数的 typedef 声明之后添加原型定义。
函数中add_values
static void add_values(List *lst)
{
ListPos pos = list_first(lst);
//..
调用函数 list_first
尚未声明。
您需要在函数 list_first
的使用前声明函数 list_first
。
例如
ListPos list_first(List *lst);
static void add_values(List *lst)
{
ListPos pos = list_first(lst);
//..
注意这个声明
typedef struct list
{
struct node head;
} List;
没有多大意义。您应该使用列表的以下声明
typedef struct list
{
struct node *head;
struct node *tail;
} List;
函数list_create
没有初始化动态分配对象的数据成员。
因此其他函数,例如 list_first
调用未定义的行为来访问未初始化的数据成员 head
就像在这个声明中一样
ListPos pos = {
.node = lst->head.next
};
implicit declaration of function list_first.
这意味着编译器已经看到一个名为list_first
的函数调用,但是您(或您在编译单元中使用的包含文件)没有提供该函数的接口(它返回的类型,或传递给它的参数的列表和类型)在旧 C 中,这是允许的,默认情况下(这可能太大胆了)函数 returns 一个 int
值并采用未定义的列表参数的数量,由此原型定义(可能不正确):
int list_first();
所以您可能需要在头文件中为该函数提供正确的定义(如果该函数是您编写的)并 #include
在您的源文件中,或者只是 #include
给出函数定义的文件。
旧版本的标准允许这样做,编译器中的默认行为如上所示,但最新版本的标准禁止这样做(好吧,如果你写了这个函数,为什么不包含一个头文件告诉编译器如何使用它?或者如果你没有,为什么要让编译器猜测而不提供正确的接口?)
这不是程序的最终实现,但程序本身有点长,所以我决定改为将其分成小块来创建。我 运行 遇到一个错误
implicit declaration of function list_first.
还有其他错误需要解决,但我想先得到一些帮助,然后再自己解决其余的问题,尽管如果您愿意,欢迎您提供额外的帮助。这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// The type for a node in the list.
struct node
{
struct node *next;
struct node *prev;
char *value;
};
// The type for a list.
typedef struct list
{
struct node head;
} List;
// The type for a list position.
typedef struct list_pos
{
struct node *node;
} ListPos;
List *list_create(void)
{
List *lst = (List*)malloc(sizeof(List));
if(lst == NULL)
{
printf("No more memory!\n");
}
return lst;
}
static struct node *make_node(const char *value)
{
struct node *result = malloc(sizeof(struct node));
result->value = strdup(value);
result -> next = NULL;
result -> prev = NULL;
return result;
}
static void add_values(List *lst)
{
ListPos pos = list_first(lst);
pos = list_insert(pos, "Apple");
pos = list_next(pos);
pos = list_insert(pos, "Banana");
pos = list_next(pos);
pos = list_insert(pos, "Citrus");
}
ListPos list_end(List *lst)
{
ListPos pos = {
.node = &lst->head
};
return pos;
}
ListPos list_first(List *lst)
{
ListPos pos = {
.node = lst->head.next
};
return pos;
}
ListPos list_next(ListPos pos)
{
struct node* node;
//pos = node -> next;
struct node *before = pos.node->prev;
struct node *after = pos.node;
node->next = after;
after->prev = node;
pos.node = node;
return pos;
}
ListPos list_insert(ListPos pos, const char *value)
{
// Create a new node.
struct node *node = make_node(value);
// Find nodes before and after (may be the same node: the head of the list).
struct node *before = pos.node->prev;
struct node *after = pos.node;
// Link to node after.
node->next = after;
after->prev = node;
// Link to node before.
node->prev = before;
before->next = node;
// Return the position of the new element.
pos.node = node;
return pos;
}
int main(void)
{
// Create an empty list.
List *lst = list_create();
add_values(lst);
return 0;
}
在使用函数的行之前必须是函数的原型或函数定义本身。在函数和您指定的其他函数的 typedef 声明之后添加原型定义。
函数中add_values
static void add_values(List *lst)
{
ListPos pos = list_first(lst);
//..
调用函数 list_first
尚未声明。
您需要在函数 list_first
的使用前声明函数 list_first
。
例如
ListPos list_first(List *lst);
static void add_values(List *lst)
{
ListPos pos = list_first(lst);
//..
注意这个声明
typedef struct list
{
struct node head;
} List;
没有多大意义。您应该使用列表的以下声明
typedef struct list
{
struct node *head;
struct node *tail;
} List;
函数list_create
没有初始化动态分配对象的数据成员。
因此其他函数,例如 list_first
调用未定义的行为来访问未初始化的数据成员 head
就像在这个声明中一样
ListPos pos = {
.node = lst->head.next
};
implicit declaration of function list_first.
这意味着编译器已经看到一个名为list_first
的函数调用,但是您(或您在编译单元中使用的包含文件)没有提供该函数的接口(它返回的类型,或传递给它的参数的列表和类型)在旧 C 中,这是允许的,默认情况下(这可能太大胆了)函数 returns 一个 int
值并采用未定义的列表参数的数量,由此原型定义(可能不正确):
int list_first();
所以您可能需要在头文件中为该函数提供正确的定义(如果该函数是您编写的)并 #include
在您的源文件中,或者只是 #include
给出函数定义的文件。
旧版本的标准允许这样做,编译器中的默认行为如上所示,但最新版本的标准禁止这样做(好吧,如果你写了这个函数,为什么不包含一个头文件告诉编译器如何使用它?或者如果你没有,为什么要让编译器猜测而不提供正确的接口?)