C++ 为C和C初始化联合函数指针++;
如何在没有错误或警告的情况下使用函数指针初始化联合? 该代码以嵌入式为目标,必须在C和C++中编译。 <>但是我遇到的问题是,直接初始化会产生一个C与C++不兼容的指针警告,而C++中的指定初始化已经被禁止。 <没有任何方法可以做到这一点而没有C和C++中的警告和错误?< /P> 最简单的例子:C++ 为C和C初始化联合函数指针++;,c++,c,initialization,unions,C++,C,Initialization,Unions,如何在没有错误或警告的情况下使用函数指针初始化联合? 该代码以嵌入式为目标,必须在C和C++中编译。 但是我遇到的问题是,直接初始化会产生一个C与C++不兼容的指针警告,而C++中的指定初始化已经被禁止。 最简单的例子: struct List { union { int (*foo)(int num, int data); int (*fee)(int num, float data); }; }; int foo_fun(int pnum
struct List {
union {
int (*foo)(int num, int data);
int (*fee)(int num, float data);
};
};
int foo_fun(int pnum, int data);
int fee_fun(int pnum, float data);
static const struct List list[] = {
{
{foo_fun},
},
{
{fee_fun},
/* C = warning: incompatible pointer types initializing 'int (*)(int, int)'
* with an expression of type 'int (int, float)'
*/
/* C++ = error: cannot initialize a member subobject of type 'int (*)(int, int)'
* with an lvalue of type 'int (int, float)':
* type mismatch at 2nd parameter ('int' vs 'float')
*/
},
/* With C++ */
{
{.fee = fee_fun},
/* ^^^^^^^^^^^^^
* C++ = warning: designated initializers are a C99 feature
*/
},
};
代码确实适用于警告不兼容指针类型
或指定的初始值设定项是C99功能
最简单的方法是删除联合体并使用空指针。然而,由于明显的缺点,这远远不是我的首选选项
阿林索尔正确地指出。确保调用了正确的函数是示例中当前省略的列表中其他元素的任务
指定的初始化将在C++20中再次完全可用。
在那之前,它们没有任何效果。除了工会,他们似乎仍在工作。(减去警告)< p>只有在C++中(C++ 20之前)初始化联盟成员的唯一方法才是UNION.< /P>中的构造函数。
初始化C中第一个之外的联合成员的唯一方法是指定初始值设定项 这并没有留下太多的回旋余地。当心前方的丑陋:
// For convenience
typedef int (*fooPtr)(int, int);
typedef int (*feePtr)(int, float);
#ifndef __cplusplus
#define INITIALIZE(x) .x =
#else
#define INITIALIZE(x)
#endif
struct List {
union X {
#ifdef __cplusplus
constexpr X(fooPtr foo_) : foo(foo_) {}
constexpr X(feePtr fee_) : fee(fee_) {}
#endif
fooPtr foo;
feePtr fee;
} x;
};
int foo_fun(int pnum, int data);
int fee_fun(int pnum, float data);
static const struct List list[] = {
{
{INITIALIZE(foo) foo_fun},
},
{
{INITIALIZE(fee) fee_fun},
},
};
不是很好,但也有一些可能性。C++具有构造函数重载。C具有
\u通用和指定的初始值设定项
typedef int foo_t (int num, int data);
typedef int fee_t (int num, float data);
typedef struct List
{
union
{
foo_t* foo;
fee_t* fee;
};
#ifdef __cplusplus
List(foo_t* f) :foo(f){}
List(fee_t* f) :fee(f){}
#define FOO_INIT(f) List(f)
#define FEE_INIT(f) List(f)
#else
#define FOO_INIT(f) { .foo = _Generic((f), foo_t*: (f)) }
#define FEE_INIT(f) { .fee = _Generic((f), fee_t*: (f)) }
#endif
} List;
int the_foo (int num, int data){ return 0;}
int the_fee (int num, float data){ return 0;}
int main (void)
{
List list_foo = FOO_INIT(the_foo);
List list_fee = FEE_INIT(the_fee);
return 0;
}
在任何一种语言中,这都应该是类型安全的 C++20中将提供指定的初始值设定项(至少是C中存在的部分)。@Mat我知道。AcAIK指定的初始化没有在C++中被禁止,它从来没有在C++中,而是在C++出现之后才在C中引入,写在<代码>中的联合构造函数是什么?除了C++中的第一个联合成员外,没有其他方法来初始化任何东西。编辑:嗯,除了第一个没有指定初始值设定者的C99联盟成员之外,没有其他方法来初始化C99联盟成员……联盟是一个丑陋的黑客。演员阵容是另一个丑陋的黑客。我不知道为什么喜欢一个丑陋的黑客胜过另一个。@Jeroen3等等,它在哪个编译器中不工作?ARMGCC 8.2似乎很高兴:。ARMclang也是如此:(说清楚,我对ARM一无所知)。我有带uVision 4的armcc v5.06捆绑包。它类似于C++的错误,需要指定的初始化器。恐怕我不能使用构造函数方法。因为我必须将它加载到flash中,所以它必须是常量。这是一个嵌入式目标。@Jeroen3我不明白。你的编译器是C编译器还是C++编译器?或者两者都有?我假设编译器是编译代码,而不是C++。在这种情况下,您应该从构造函数的代码< >初始化< /代码>中得到指定的初始化器:标记它们<代码> CONTXPRP</代码>,然后得到编译时的列表(答案更新)。这与CAR99提供给ARMCC 5.06,并与明W32-730 C和C++一起使用。