C 函数指针 - 未分配但仍然有效。有默认行为吗?
C Function pointer - not assigned but still works. Is there default behavior?
我从一位高素质的讲师给我的程序中获得了这段代码。注意下面的函数指针 cmpfn。它用作比较运算符。我阅读了一些函数指针,它们很有意义。但是,在这个代码库中的任何地方,我都没有看到它被分配给了一个实际定义的函数,就像我在网上阅读的教程中看到的那样。它从未在任何地方定义和分配,但它似乎可以工作。是否有一些默认行为,或者如果不像 cmpfn = &function_defined_elsewhere;
那样分配它,您将如何使它工作?还有为什么他会选择使用这个函数指针而不是直接比较运算符?
/**
* Find an element in the list
*
* cmpfn should return 0 if the comparison to this node's data is equal.
*/
void *llist_find(struct llist *llist, void *data, int (*cmpfn)(void *, void *))
{
struct llist_node *n = llist->head;
if (n == NULL) {
return NULL;
}
while (n != NULL) {
if (cmpfn(data, n->data) == 0) {
break;
}
n = n->next;
}
if (n == NULL) {
return NULL;
}
return n->data;
}
编辑(回复反馈):已解决!下面是一般 public edification/curiosity 但现在对我来说很有意义。感谢您的宽容。
我明白了,我需要找到调用此函数的位置。上面的代码在一个名为 llist.h 的文件中,指向函数 (p2f) 的指针在一个名为 hashtable.c 的文件中被调用——实际上是两次。他实际上经常使用 p2f。
这是调用“p2f 托管”函数的一个实例:
/**
* Get from the hash table with a binary data key
*/
void *hashtable_get_bin(struct hashtable *ht, void *key, int key_size)
{
int index = ht->hashf(key, key_size, ht->size);
struct llist *llist = ht->bucket[index];
struct htent cmpent;
cmpent.key = key;
cmpent.key_size = key_size;
struct htent *n = llist_find(llist, &cmpent, htcmp); // HERE
if (n == NULL) { return NULL; }
return n->data;
}
因此正在通过 htcmp。以前我认为你必须将 p2f 分配给带有“=”的函数,但你也可以通过传递给调用函数来完成。今天才知道这些!
这里是 htcmp 的定义:
/**
* Comparison function for hashtable entries
*/
int htcmp(void *a, void *b)
{
struct htent *entA = a, *entB = b;
int size_diff = entB->key_size - entA->key_size;
if (size_diff) {
return size_diff;
}
return memcmp(entA->key, entB->key, entA->key_size);
}
所以很明显 returns 一个 int,取决于两个 htent(哈希表条目)之间的差异,注意大小差异或调用强大的 memcmp 函数。
这是一个挑战。基础知识是有道理的,但他的代码很忙。我必须在睡梦中巩固它。有如此多的结构和指向函数的指针以及许多其他交互,但它曾经是并且现在仍然是一次很棒的学习体验。
您在此参数中设置了指针。所以,当你调用这个函数时,我会自动自动设置这些指针。所以,我认为你应该看看这个功能的调用。然后你就会得到你问题的答案
void *llist_find(struct llist *llist, void *data, int (*cmpfn)(void *, void *))
当您调用函数 llist_find 时,您应该将引用传递给该函数,该函数必须具有与 llist_find.
预期相同的原型
为了回答您的问题,使用指向函数的指针非常有帮助,尤其是当您使用的结构可以对结构的一个或多个成员执行比较(本例)时。此外,由于该函数使用空指针,您可以使用相同的 llist_find 来处理不同类型结构的列表。
我从一位高素质的讲师给我的程序中获得了这段代码。注意下面的函数指针 cmpfn。它用作比较运算符。我阅读了一些函数指针,它们很有意义。但是,在这个代码库中的任何地方,我都没有看到它被分配给了一个实际定义的函数,就像我在网上阅读的教程中看到的那样。它从未在任何地方定义和分配,但它似乎可以工作。是否有一些默认行为,或者如果不像 cmpfn = &function_defined_elsewhere;
那样分配它,您将如何使它工作?还有为什么他会选择使用这个函数指针而不是直接比较运算符?
/**
* Find an element in the list
*
* cmpfn should return 0 if the comparison to this node's data is equal.
*/
void *llist_find(struct llist *llist, void *data, int (*cmpfn)(void *, void *))
{
struct llist_node *n = llist->head;
if (n == NULL) {
return NULL;
}
while (n != NULL) {
if (cmpfn(data, n->data) == 0) {
break;
}
n = n->next;
}
if (n == NULL) {
return NULL;
}
return n->data;
}
编辑(回复反馈):已解决!下面是一般 public edification/curiosity 但现在对我来说很有意义。感谢您的宽容。
我明白了,我需要找到调用此函数的位置。上面的代码在一个名为 llist.h 的文件中,指向函数 (p2f) 的指针在一个名为 hashtable.c 的文件中被调用——实际上是两次。他实际上经常使用 p2f。
这是调用“p2f 托管”函数的一个实例:
/**
* Get from the hash table with a binary data key
*/
void *hashtable_get_bin(struct hashtable *ht, void *key, int key_size)
{
int index = ht->hashf(key, key_size, ht->size);
struct llist *llist = ht->bucket[index];
struct htent cmpent;
cmpent.key = key;
cmpent.key_size = key_size;
struct htent *n = llist_find(llist, &cmpent, htcmp); // HERE
if (n == NULL) { return NULL; }
return n->data;
}
因此正在通过 htcmp。以前我认为你必须将 p2f 分配给带有“=”的函数,但你也可以通过传递给调用函数来完成。今天才知道这些!
这里是 htcmp 的定义:
/**
* Comparison function for hashtable entries
*/
int htcmp(void *a, void *b)
{
struct htent *entA = a, *entB = b;
int size_diff = entB->key_size - entA->key_size;
if (size_diff) {
return size_diff;
}
return memcmp(entA->key, entB->key, entA->key_size);
}
所以很明显 returns 一个 int,取决于两个 htent(哈希表条目)之间的差异,注意大小差异或调用强大的 memcmp 函数。
这是一个挑战。基础知识是有道理的,但他的代码很忙。我必须在睡梦中巩固它。有如此多的结构和指向函数的指针以及许多其他交互,但它曾经是并且现在仍然是一次很棒的学习体验。
您在此参数中设置了指针。所以,当你调用这个函数时,我会自动自动设置这些指针。所以,我认为你应该看看这个功能的调用。然后你就会得到你问题的答案
void *llist_find(struct llist *llist, void *data, int (*cmpfn)(void *, void *))
当您调用函数 llist_find 时,您应该将引用传递给该函数,该函数必须具有与 llist_find.
预期相同的原型为了回答您的问题,使用指向函数的指针非常有帮助,尤其是当您使用的结构可以对结构的一个或多个成员执行比较(本例)时。此外,由于该函数使用空指针,您可以使用相同的 llist_find 来处理不同类型结构的列表。