如何将C-struct指定的初始值设定项重写为C89(resp MSVC C编译器)
伙计们,我有个问题: 通常在C99 GCC(cygwin/MinGW/linux)中,C结构中的初始值设定项有点符号语法。如何将C-struct指定的初始值设定项重写为C89(resp MSVC C编译器),c,visual-c++,struct,initialization,c89,C,Visual C++,Struct,Initialization,C89,伙计们,我有个问题: 通常在C99 GCC(cygwin/MinGW/linux)中,C结构中的初始值设定项有点符号语法。 像这样: //HELP ME HOW TO REWRITE THIS (in most compact way) to MSVC static struct my_member_t my_global_three[] = { {.type = NULL, .name = "one"}, {.type = NULL, .name = "two"}, {
像这样:
//HELP ME HOW TO REWRITE THIS (in most compact way) to MSVC
static struct my_member_t my_global_three[] = {
{.type = NULL, .name = "one"},
{.type = NULL, .name = "two"},
{.type = NULL, .name = "three"},
};
在头文件中定义的my\u memeber\t
为:
struct my_member_t {
struct complex_type * type;
char * name;
int default_number;
void * opaque;
};
我正在MSVC 9.0(visualstudio 2008)中编译linux代码,在cygwin/MinGW上运行正常。
但是cl无法编译此代码(因为C99实现糟糕):
错误C2059:语法错误:'.
问题:
如何以MSVC可以编译的方式重写(许多)全局结构
向您致以最诚挚的问候,并感谢您的建议……C99的实施情况如何?我不认为VC2008中的C编译器甚至试图实现C99。它可能借用了一些特性,但实际上是一个C89/90编译器
只需删除字段名标签
static struct my_member_t my_global_three[] = {
{ NULL, "one"},
{ NULL, "two"},
{ NULL, "three"},
};
在这种情况下很容易,因为初始值设定项在原始代码中的顺序与结构中字段的顺序相同。如果顺序不同,您必须在无标记C89/90版本中重新排列它们
如果它确实是您的my_member\t
,那么您应该将字符串指针声明为const char*
,或者停止使用字符串文本初始化这些成员。谢谢您的信息,Nico
/*
* Macro for C99 designated initializer -> C89/90 non-designated initializer
*
* Tested. Works with MSVC if you undefine HAVE_DESIGNATED_INITIALIZERS. Cscope also
* groks this.
*
* ("SFINIT" == struct field init, but really, it can be used for array initializers too.)
*/
#ifdef HAVE_DESIGNATED_INITIALIZERS
#define SFINIT(f, v) f = v
#else
#define SFINIT(f, v) v
#endif
struct t {
char f1;
int f2;
double f3;
};
struct t t = {
SFINIT(.f1, 'a'),
SFINIT(.f2, 42),
SFINIT(.f3, 8.13)
};
但是,我发现,对于内部带有数组的结构来说,这是行不通的。我建议对C99和MSVC(在MSVC++2010 Express中验证)进行此修改:
通过这种方式,您可以为MSVC和其他编译器使用一个文件。就是这样:-)假设未列出的字段必须显式初始化为0/NULL(因此arity匹配)。未列出的尾部字段设置为0。与C99不同,您不能跳过其他字段,因为它们必须按顺序给定。@DinGODzilla:Arity在C89/90中不需要匹配,只要您每次要跳到数组的下一个成员时都使用一对嵌套的{}
。这意味着您只需初始化结构的前导元素,而尾随元素将自动设置为零。在这种特殊情况下,在C99中用NULL
初始化type
字段是不必要的,只需.name=“something”
就足够了(type
将自动设置为NULL),但在C89/90中,您必须明确指定NULL
字段,才能进入下一个字段name
@DinGODzilla:。。。。。换句话说,它看起来像是C99风格的初始化器是由C89/90风格的初始化器直接翻译而来的,它需要一个显式的<代码> null <代码>第一个字段:)……它实际上是一个C89/90编译器。“不,MSVC真的是C++编译器。他们真的不再谈论C了。请注意,VS 2013中添加了指定初始值设定项功能:我看不出这是如何在C89中实现指定初始值设定项功能的?如果我更改了值的顺序,或者省略了一些值,这就是此功能的全部要点,该怎么办?:-1:这根本不是一个可移植的解决方案。这里基本上没有定义编译器之间的初始化行为。在HAVE_designed_INITIALIZERS==0
的情况下,这看起来更像是一种复杂的参数注释方式。与Nico的答案相同,这是不可移植的,因为初始化最终仍取决于传递值的顺序。在最坏的情况下,此代码使用不同的编译器编译,但结果不同。。。
#ifdef HAVE_DESIGNATED_INITIALIZERS
#define SFINIT(f, ...) f = __VA_ARGS__
#else
#define SFINIT(f, ...) __VA_ARGS__
#endif
typedef struct {
int val;
int vecB[4];
int vecA[4];
} MyStruct_ts;
static const MyStruct_ts SampleStruct =
{
SFINIT(.val , 8),
SFINIT(.vecB , { 1, -2, 4, -2}),
SFINIT(.vecA , { 1, -3, 5, -3}),
};