【问题标题】:Alias a new name for a function (C)为函数命名的别名 (C)
【发布时间】:2014-11-27 11:49:12
【问题描述】:

我一直在尝试在 C 中实现队列结构,使用 C 中链表的另一种实现。

队列需要的一些函数已经在linked_list.h中定义了,我想给它们取一个新名字;例如,为 create_list() 别名 create_queue()。

由于我对 C 编程相当陌生,因此我在网上查找了一种方法来执行此操作,然后遇到了函数指针的话题。这似乎是做我想做的事情的正确方法,但是当我尝试它时:

#include "linked_list.h"

typedef list_t queue_t; // list_t is the list type defined in linked_list.h,
                        // as well as the functions such as create_list()

queue_t (*create_queue)() = NULL; // Setting the function pointer to NULL
create_queue = &create_list; // Aliasing create_queue() for create_list()

当我尝试编译时,我收到错误和警告:

  • 错误:使用不同类型重新定义“create_queue”:“int”与“queue_t (*)()”
  • 警告:缺少类型说明符,默认为 'int'

我的代码中缺少什么?我不想要我的问题的完整解决方案,只是重定向到正确的方式。


这是 create_list():

list_t create_list(){
/* Creates and returns a NULL list, with index and value zeroed */
list_t list;
malloc(sizeof(list_t));

list.global_index = 0; /* Global index to keep how many nodes in the list, since no loops are allowed */
list.total_value = 0; /* Total value to keep total value of nodes in the list, since no loops are allowed */
list.head = NULL;
list.last = NULL;

return list;
}

以及结构定义:

struct int_node {
int value;
struct int_node * previous; /* Needed to go to previous nodes with no loops */
struct int_node * next;
};

struct int_list {
int global_index;
int total_value;
struct int_node * head;
struct int_node * last;
};

/* Typedefs */
typedef struct int_node node_t;
typedef struct int_list list_t;

【问题讨论】:

  • 请给出原型和你的错误所在
  • 我添加了 create_list() 原型。错误和警告都在同一行:create_queue = &create_list;
  • 你能把list_t的结构也展示一下吗?
  • 你能显示编译器警告你的那一行吗?
  • @Ilay 和报错是同一行:create_queue = &create_list;

标签: c linked-list queue alias typedef


【解决方案1】:

尝试替换这些行:

queue_t (*create_queue)() = NULL; // Setting the function pointer to NULL
create_queue = &create_list; // Aliasing create_queue() for create_list()

用这一行:

queue_t (*create_queue)() = &create_list; // Aliasing create_queue() for create_list()

我的编译没有错误。

【讨论】:

  • @MatanAbudy 您不能在函数之外有语句,只有声明和初始化程序。如果您将作业移至main,第一个将起作用。
【解决方案2】:

如果链表中存在相同的函数,则正确的方法是创建函数包装器。例如,如果您有

void linklist_add (int x);

并且想要创建一个 queue_add 函数,你可以将它实现为:

void queue_add (int x)
{
  linklist_add(x);
};

任何从“linklist_t”到“queue_t”等的类型转换都可以在包装函数内部处理。

现在阅读本文后,至少有十个人会立即开始尖叫额外的函数调用开销。 不用担心这个! 编译器可能能够优化或内联函数。即使没有,额外的函数调用开销在 99% 的所有系统上都是可以忽略的。

努力使您的代码尽可能具有可读性,这应该始终是主要关注点。简单的解决方案往往是最好的解决方案。只有在实际需要出现时才应该考虑优化。

函数指针可以工作,但它必须是一个全局变量,这不是一个好主意。此外,函数指针往往会生成不可读的代码,尤其是当您不对它们进行类型定义时。函数指针应该用于泛型编程,而不是调用者接口。

【讨论】:

  • 非常感谢您的解释!我有两个问题:1.调用函数包装器和调用函数指针的可读性有什么区别?在我看来几乎一样。 2. 为什么函数指针必须是全局变量?
  • @MatanAbudy 首先是 C 程序员事实上的行业标准。当给定诸如队列之类的 ADT 时,您期望在 h 文件中存在函数列表。您不应该摆弄全局变量或 ADT 的内部结构,那将是非常糟糕的程序设计。函数指针必须是全局变量,否则调用者将无权访问它。如果你给 C 程序员一个全局函数指针列表作为 ADT 的接口,他们会很困惑。
  • 好的,我现在明白了。非常感谢!
  • @MatanAbudy 还有私有封装问题。如果你的函数指针不是常量指针,调用者可以让它们指向别处,要么是故意的,要么是因为他们疯了,要么是错误的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-03
  • 2012-10-30
  • 1970-01-01
  • 2013-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多