Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用_Generic关键字的宏的Eclipse CDT语法错误_C_Eclipse Cdt - Fatal编程技术网

使用_Generic关键字的宏的Eclipse CDT语法错误

使用_Generic关键字的宏的Eclipse CDT语法错误,c,eclipse-cdt,C,Eclipse Cdt,我使用的是内置CDT9.3.0的氧气 当我使用我定义的使用_Generic的宏时,所有这些宏的使用都带有“syntax error”的下划线,但是项目编译很好(设置为使用我的makefile) 在阅读了一个so问题之后,由于eclipse的代码分析可能不支持从C11开始的泛型,我尝试将宏定义的符号定义为空,但没有成功。(在项目设置中,C/C++常规->路径和符号->符号选项卡,GNU C,添加了不带值的符号转换(…),并添加了符号转换(X),以及CONVERT()和不带值的转换) 例如,我的宏是

我使用的是内置CDT9.3.0的氧气

当我使用我定义的使用_Generic的宏时,所有这些宏的使用都带有“syntax error”的下划线,但是项目编译很好(设置为使用我的makefile)

在阅读了一个so问题之后,由于eclipse的代码分析可能不支持从C11开始的泛型,我尝试将宏定义的符号定义为空,但没有成功。(在项目设置中,C/C++常规->路径和符号->符号选项卡,GNU C,添加了不带值的符号转换(…),并添加了符号转换(X),以及CONVERT()和不带值的转换)

例如,我的宏是:

#define FIRST_(_1, ...) _1
#define FIRST(...) FIRST_(__VA_ARGS__, _1, _2, _3)

#define CONVERT(...)                            \
                _Generic((FIRST(__VA_ARGS__)),  \
                    char*       : toText,   \
                    int         : toInt,    \
                    ) (__VA_ARGS__)
和使用点,这会导致语法错误:

void* test = CONVERT("testme");

正如@ErikW指出的,
\u Generic
是一个C11特性,Eclipse CDT的解析器还不支持它。跟踪添加对它的支持

(顺便说一句,非常欢迎使用Eclipse CDT的C11支持!)


可以使用宏来解决这个问题

试图在“路径和符号”中定义另一个版本的
CONVERT(…)
宏的问题在于,此处定义的宏被视为是在文件的最顶端编写的。实际代码中的后续重新定义将覆盖“路径和符号”中的定义

我可以想出两种方法来实现这一点:


方法1

CDT定义了一个特殊的宏
\uuu CDT\u PARSER\uuu
,它在解析代码时计算为true,但在实际编译代码时计算为false

您可以利用此功能为CDT定义不同版本的
CONVERT(…)

#ifdef __CDT_PARSER__
    #define CONVERT(...)
#else
    #define CONVERT(...)                            \
                    _Generic((FIRST(__VA_ARGS__)),  \
                        char*       : toText,   \
                        int         : toInt,    \
                        ) (__VA_ARGS__)
#endif
这几乎有效,但不完全有效。我们仍然会遇到语法错误,因为这一行:

void* test = CONVERT("testme", 42);
void* test = CONVERT("testme", 42);
现在将扩展到:

void* test = ;
void* test = _Generic((FIRST("testme", 42)),  \
                    char*       : toText,   \
                    int         : toInt,    \
                    ) ("testme", 42)
void* test = ("testme", 42);
正如您所看到的,我们实际上不希望
CONVERT(…)
的扩展为空。我们需要一个将解析为变量初始值设定项的扩展<代码>0将起作用:

#ifdef __CDT_PARSER__
    #define CONVERT(...) 0
#else
    ...
#endif

方法2

我们可以将
\u Generic(…)
本身定义为用于CDT的宏,而不是定义不同版本的
CONVERT(…)

这一次,我们可以在“路径和符号”中这样做,因为在代码中没有对
\u Generic(…)
的重新定义会把它搞砸

因此,让我们在“路径和符号”中定义一个符号,名称为
\u Generic(…)
,值为空

现在,这一行:

void* test = CONVERT("testme", 42);
void* test = CONVERT("testme", 42);
将扩展到:

void* test = ;
void* test = _Generic((FIRST("testme", 42)),  \
                    char*       : toText,   \
                    int         : toInt,    \
                    ) ("testme", 42)
void* test = ("testme", 42);
这将反过来扩展到:

void* test = ;
void* test = _Generic((FIRST("testme", 42)),  \
                    char*       : toText,   \
                    int         : toInt,    \
                    ) ("testme", 42)
void* test = ("testme", 42);
解析(
(“testme”,42)
解析为带括号的逗号表达式,因此是有效的初始值设定项)

这种方法的优点是,您不需要修改实际代码,而且它可以处理
\u Generic
宏的所有用法,而不仅仅是
CONVERT
中的用法


另一方面,对于
\u Generic
宏的某些其他用途,此特定扩展可能无法解析。如果是这样的话,您可能会想出一个不同的扩展来解析所有用途,或者您可以使用方法1。

\u Generic
来自C11标准。据我所知,Eclipse的“智能感知”还不支持它。