Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.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无效_C - Fatal编程技术网

将复合文字传递给_Generic无效

将复合文字传递给_Generic无效,c,C,在以下代码中: struct Person { char* name; int age; }; struct Book { char* title; char* author; }; #define MYTYPE(X) _Generic((X), int: "int", float: "float", double: "double", struct Book: "book",

在以下代码中:

struct Person {
    char* name;
    int age;
};

struct Book {
    char* title;
    char* author;
};
#define MYTYPE(X)   _Generic((X), int: "int", float: "float", double: "double", struct Book: "book", struct Person: "person", default: "other")
以下工作:

struct Book ulysses = {"ulysses", "james"};
printf("%s\n", MYTYPE(ulysses));
struct Person jim;
jim = (struct Person) {"Tom", 20};
printf("%s\n", MYTYPE(jim));
但是,如果我尝试传递复合文字,它将失败:

printf("%s\n", MYTYPE((struct Person){"Tom", 10}));
gen.c:25:53:错误:宏“MYTYPE”传递了2个参数,但只接受1个
printf(“%s\n”,MYTYPE((struct Person){“Tom”,10}))
............................................................................... ^

struct Person
传递到
MYTYPE
宏时出现了什么问题


更新:在parens中双重包装表达式似乎可以解决这个问题,但我不确定为什么需要这样做:

printf("%s\n", MYTYPE(((struct Person){"Tom", 10})));
typedef结构人{
字符*名称;
智力年龄;
}t_Person;//(对不起,我养成了这个习惯)
请注意,如果您声明它,则不再需要对其进行双重包装:

t_Person a={“Tom”,10};
printf(“%s\n”,MYTYPE(((t_Person){“Tom”,10}));->作品
printf(“%s\n”,MYTYPE(a));->有效,保存4个括号。
我的猜测是MYTYPE不知道自己的内部是什么,因为它可能是int、float等。。。因此编译器认为括号之间的结构实际上是一个强制转换,而不是一个声明,添加另一个括号可以解决冲突

我可以用以下几点来证明:

#定义MYTYPE(X)(X)、char:“char”、int:“int”、float:“float”、double:“double”、struct Book:“Book”、struct Person:“Person”、default:“other”)
printf(“%s\n”,MYTYPE((int){'a'}));//->输出整数
printf(“%s\n”,MYTYPE((char){'a'}));//->输出字符
。转换仅在类型域中执行:它丢弃顶级cvr限定符和原子性,并将数组到指针/函数到指针转换应用于控制表达式的类型,而不会引发任何副作用或计算任何值


您遇到的问题是由于预处理器语法造成的
MACRONAME(a,b)
意味着使用两个参数
a
b
调用MACRONAME,而不管
a
、逗号和
b
的组合是否恰好形成了语义上有效的表达式。(在预处理阶段,我们还没有将标记排列成表达式)

例外情况与字符串文字和匹配的括号对有关:

  • 字符串文字中的逗号不是参数分隔符
  • 匹配的一对括号内的逗号不是分隔符。(这指的是参数列表中的括号,而不是宏替换语法中的括号)

因此,双括号起作用的原因是:
MACRONAME((a,b))
意味着用一个参数
(a,b)
调用
MACRONAME
,您用两个参数调用了
MYTYPE
(struct Person){“Tom code>和
10}
。与括号不同,大括号在预处理器级别上没有语法意义,并且不禁止逗号作为宏参数分隔符的作用。您需要在复合文本中加括号以避免这种情况。或者,在某些情况下(包括您的情况),您可以使用
..
\uu VA\u ARGS\uuu
生成一个可避免问题的可变宏。另请参见我的问题:

@chux:是的,这是有效的,但我很好奇,如果我已经在函数调用中,为什么需要这个部分
()
Hmmmm………什么编译器和版本?@Shawn gcc 7.5.0(在c代码中执行
\uu version\uuuu
,这就是你的意思吗?)使用较新的gcc版本(和clang)在门闩上?可能是一个编译器错误,希望已经修复。为了澄清这一点,OP的宏调用有两个参数:
(struct Person){“Tom”
10}
@M.M。请您解释一下匹配括号内的逗号如何不是分隔符。
有效吗?这是否意味着除了函数调用本身之外还有一个括号?所以…
函数((a,b))
而不是
函数(a,b)
?@carl.hiass是的,我在最后一段中给出了这个例子。此外,这些不是函数调用,而是宏替换
MACRONAME(参数列表)
是宏替换调用的语法。这些括号不是论点列表的一部分,这是一个很好的解释。你能解释一下
..
是如何解决这个问题的另一种方法吗?@carl.hiass:如果宏只接受一个变量
..
参数,
\uu VA\u ARGS\uuu
将扩展到由逗号分隔的整个参数集,因此它将“重新组合”一个拆分为多个参数的复合文字。我忘了在没有非变量参数的情况下使用
在技术上是否是有效的C语言,但我所知道的所有编译器都支持它,我认为是的。