C ++中的转换无效

时间:2017-05-11 12:48:07

标签: c++ type-conversion

上下文:

我有一段代码在编译为C时编译并运行正常,我试图将它移植到C ++,以便能够在未来的C ++程序中使用它。

我在我的程序中使用这种结构数据类型。

 typedef struct MessageDigest{
      int32_t digestLen;
      void* ctx;
      int (*Init)(void* c);
      int (*update)(void* c, const void* data, size_t len);
      int (*Final)(uint8_t* md, void* c);
   }MessageDigest;

在我的main函数中,我正在影响结构的标识符:

    MessageDigest* newMD;
    /*Other code*/
    newMd->Init=&SHA1_Init; //The problem is here

我收到此错误:

 invalid conversion from ‘int (*)(SHA_CTX*) {aka int (*)
 (SHAstate_st*)}’ to ‘int (*)(void*)’ [-fpermissive]

我尝试使用static_cast<>,但它无效

1 个答案:

答案 0 :(得分:4)

该问题的错误很清楚。你宣布

int  SHA1_Init(SHAstate_st*);

由于其参数声明为SHAstate_st*,它是否与函数指针声明不兼容,该声明期望参数为void *

你有两种方法。简短的是使用reinterpret_cast。我们知道,对于任何当前的编译器,指向void或struct的指针只是一个地址,它应该可以工作,但恕我直言,它会严格阅读标准来调用未定义的行为:

newMd->Init=reinterpret_cast<int (*)(void *)(&SHA1_Init); // should work but not really standard compliant

正确的是包裹SHA1_Init

int SHA1_Init_void(void *p) {
    return SHA1_Init(static_cast<SHAstate_st *>(p));
}

然后你可以正确地使用它:

newMd->Init = &SHA1_init_void;

但无论如何,你是采取了错误的方式:你正在尝试用C ++编译C代码,这通常会导致像这样的许多小错误。它们确实是不同的语言,并且在角落情况下具有特定的语义。并且它通常会导致代码不能使用C ++语言的所有功能,主要是在编译时键入安全保证。

通常,指向C结构中带有void *参数的函数的指针通常可以通过C ++中的方法覆盖来更好地表达。它肯定会涉及更多的初始工作,但恕我直言,你应该考虑重写现代C ++中的更高级别的代码(使用类,构造函数,方法和派生,可选模板)并调用更低级别的C函数。您将获得更多可维护的代码并在将来获得收益。在一个项目中混合使用C和C ++转换单元非常合适,您只需将C相关包含文件放在C ++源文件的extern "C" { ... }块中。常见的用法是将其直接放在受.h保护的#ifdef __cplusplus文件中,并在其他SO问题中进行演示:Combining C++ and C - how does #ifdef __cplusplus work?