【问题标题】:Unsure of how to cast parameters of a function in C to void *不确定如何将 C 中函数的参数转换为 void *
【发布时间】:2014-06-20 12:27:42
【问题描述】:

我正在编写一个通用哈希表,并创建了一个 typedef:

typedef unsigned long(*hashFunction_t)(void*,unsigned long);

表示散列函数。

然后我在函数 add 中使用这个:

int add(HashTable *table, hashFunction_t h, void *data);

但是,我在以下行收到警告“从不兼容的指针类型初始化”:

hashFunction_t hash = JenkinsHash;

因为JenkinsHash有参数:

unsigned long JenkinsHash(const char *str, unsigned long mod);

所以我的问题是,我如何将 JenkinsHash 转换为具有参数:

(void*,unsigned long)

感谢您的帮助!

【问题讨论】:

  • hashFunction_t hash = (hasFunction_t)JenkinsHash; ?您也可以尝试在 typedef 中使用空括号:typedef unsigned long(*hashFunction_t)();
  • 只需声明JenkinsHash() 为其第一个参数采用void *。您可以在函数开头将其转换为const char *
  • 感谢@Chnossos 成功了!现在你这么说似乎很明显。感谢您的帮助。
  • 我不得不问:unsigned long 参数的目的是什么?请不要说它是表大小,被调用函数负责执行取模而不是 you 执行它。只是好奇。为什么哈希函数是add() 函数的参数?如果有的话,它应该是表本身的 属性,在初始化期间设置。
  • @WhozCraig unsigned long 用于表大小。这是一个学校项目,我们得到了 JenkinsHash。我不太清楚你所说的“你”是什么意思。为什么 JenkinsHash(或任何其他散列函数)执行模数是一件坏事?至于设置表格的属性,那确实更有意义!我是 C 的新手,这似乎是一种更合乎逻辑、更“客观”的方式,但我不确定是否有一种干净的方式来做到这一点。我现在看到有。

标签: c casting function-pointers


【解决方案1】:

在不调用未定义行为的情况下执行此操作的最佳方法是创建一个新的 thunk 函数,该函数具有为您执行强制转换的正确签名。开销将是最小的,并且您可以避免非常不安全的类型转换。

unsigned long JenkinsHashThunk(void *str, unsigned long mod)
{
    return JenkinsHash((const char*)str, mod);
}

【讨论】:

  • void * 必须与char * 具有相同的表示形式,所以如果有这样的事情,这将是不安全类型转换规模的较小端:)
  • @MattMcNabb UB 就是这样。虽然这是一个合理的假设,但并不要求参数的类型对函数指针本身的表示有任何影响。如果实现需要,它们可以存在于完全不同的世界中,就像标准假定函数指针与数据指针不兼容,除非实现明确允许。
猜你喜欢
  • 1970-01-01
  • 2019-04-13
  • 2015-04-15
  • 2017-04-18
  • 2015-08-26
  • 2018-12-10
  • 1970-01-01
  • 1970-01-01
  • 2012-11-21
相关资源
最近更新 更多