【问题标题】:Invalid conversion from 'int' to 'void (*)(void*)' in MinGW 7.3.0 32bit在 MinGW 7.3.0 32 位中从 'int' 到 'void (*)(void*)' 的无效转换
【发布时间】:2021-05-26 20:38:25
【问题描述】:

我必须将纯 C .h 文件集成到我的 C++ 项目(Qt GUI)中。为此,我必须避免一些带有棘手替换的函数指针。您可以在下面看到的一段代码之前在 MinGW 5.3.0 C++ 中编译时没有任何问题。但是当我尝试使用更新鲜的编译器(C++ 为 7.3.0)时,我收到一个错误“从 'int' 到 'void ()(void)' 的无效转换”,但它仍然可以毫无问题地编译与 C 相同的 7.3.0。

void func_to_avoid( void* );
void func_to_avoid2( void* );

#ifdef MY_PART
  #define SOME_MACROS( func )       0
  #define SOME_MACROS2( func )      0

#endif

typedef struct
{
#ifdef MY_PART
    void            (*func)(void*);
#else
    AvoidedFunction_t  func;
#endif
}type_descr_t;


const type_descr_t types[]
={
//...
{   
 // SOME_MACROS( func_to_avoid )   // this expression compiles without any problem
    SOME_MACROS( func_to_avoid ) + SOME_MACROS2( func_to_avoid2 )  // **compilation error!**
}
//...
};

问题: 编译器给我带有“+”的宏表达式的错误。如何解决?

我认为这是一个铸造问题,但我自己无法解决。当然,我总是可以返回到以前的编译器版本或使用另一个编译器(例如,msvc),但它看起来根本不像一个解决方案。 是否有任何转换解决方案来解决此编译问题?

更新:下面的代码允许重现错误。正如我所说,它正在使用 C 编译器和 5.3.0 MinGW C++。

main.c

void func_to_avoid( void* );
void func_to_avoid2( void* );

#define MY_PART
#ifdef MY_PART
#define SOME_MACROS( func )     0
#define SOME_MACROS2( func )    0

#endif

typedef struct
{
#ifdef MY_PART
    void            (*func)(void*);
#else
    AvoidedFunction_t  func;
#endif
}type_descr_t;


const type_descr_t types[]
={
{
    SOME_MACROS( func_to_avoid )+SOME_MACROS2( func_to_avoid2 )
}};

int main()
{
    return 0;
}

【问题讨论】:

  • 请提供minimal reproducible example。 MY_PART 定义了吗?如果没有定义怎么办?然后SOME_MACROS 将导致如下错误:godbolt.org/z/Mse9n8
  • 我不完全理解,但你的问题归结为int* x = 0; vs int* x = 0+0;,后者被拒绝并出现同样的错误。为什么要首先添加函数指针?
  • 如果您使用 GCC 或 Clang,请尝试启用 -E 标志以查看宏是如何扩展的。
  • 你想用+ 构造来实现什么?不应该是{SOME_MACROS( func_to_avoid )}, {SOME_MACROS2( func_to_avoid2 )}吗?
  • “模拟”不需要的函数不是解决这个问题的更聪明的方法吗?即:void dummy_scanf (const char*s,...){} 然后#define scanf dummy_scanf。这应该编译为无操作。

标签: c++ c compiler-errors mingw


【解决方案1】:

由于这是 C++(在 C 中有所不同),您的问题归结为

int* x = 0;

对

int* x = 0+0;

后者不编译。 Gccs 错误消息与您的错误消息或多或少相同,而 clangs 更有帮助:

<source>:35:11: error: cannot initialize a variable of type 'int *' with an rvalue of type 'int'
    int* x = 0+0;
          ^   ~~~

你做不到。我不能推荐你做什么,因为它不太清楚添加两个函数指针的目的(在MY_PART没有定义的情况下)应该是什么。

【讨论】:

  • 嗯,你是怎么从 clang 那里得到这个消息的? int* x = 0+0; 符合 C.clang 版本 11 正确表示“警告:计算结果为零的表达式被视为 'int *' [-Wnon-literal-null-conversion] 类型的空指针常量”
  • @Lundin 哦,对不起。我只是假设它是 C++ 而没有首先澄清。
  • 哦,对了,又一个标签错误的惨败。或者好吧,OP 在 C++ 中使用 C 代码,所以实际上这两个标签的使用都是有效的。
  • @Lundin 实际上 OP 声明它是一个编译为 C++ 的 C 头文件。我仍然认为 C 标签可以/应该被删除(但这种错误标记的情况确实更糟)
  • 目前的政策是在两种语言之间移植代码时可以同时使用这两个标签。在这种情况下,C 和 C++ 对空指针的处理方式不同,这不是一个明显的错误。
【解决方案2】:

解决方案

其实我做到了!你的 cmets 迫使我更加努力地思考,我发现了如何制作这个“嘲弄”的把戏。我现在编译了这段代码,没有任何警告。它的用途是什么?我需要的是从 const struct types[] 中提取某些字段的值。我确信对于该任务还有其他解决方案,但这个非常适合我。

void func_to_avoid( void* );
void func_to_avoid2( void* );

#define MY_PART
#ifdef MY_PART
#define SOME_MACROS( func )     0
#define SOME_MACROS2( func )    0

#endif

typedef struct
{
   char* info_example1; // for clarification
#ifdef MY_PART
    //void          (*func)(void*);
    int func;
#else
    AvoidedFunction_t  func;
#endif
}type_descr_t;


const type_descr_t types[]
={
{
    "info_ex1",
    //I don't need this variable and now I can just skip it
    SOME_MACROS( func_to_avoid )+SOME_MACROS2( func_to_avoid2 ) 
}};

int main()
{
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    • 2013-08-19
    • 2015-11-27
    • 2016-06-06
    • 1970-01-01
    相关资源
    最近更新 更多