p.s.-我为简单目的而采用了int和int *,它也可以是struct and struct *。
我正在尝试实现一个宏来复制一个变量中存在的数据为另一个独立于变量数据类型的宏,在下面的解决方案中,我使用的是" _ generic"编译器功能。程序1:
#include<stdio.h>
#include <string.h>
#define copyVar(var,newVar) _Generic((var),int:({memcpy(newVar,(void *)&var,sizeof(int));}),
int *:({memcpy(newVar,(void *)var,sizeof(int));}),default:newVar=var)
int main() {
int data = 2;
int *copy;copy = (int *)malloc(sizeof(int));
copyVar(data,copy);
printf("copied Data=%i",*copy);
}
程序2:
#include<stdio.h>
#include <string.h>
#define copyVar(var,newVar) _Generic((var),int:({memcpy(newVar,(void *)&var,sizeof(int));}),
int *:({memcpy(newVar,(void *)var,sizeof(int));}),default:newVar=var)
int main() {
int data = 2;
int *copy;copy = (int *)malloc(sizeof(int));
copyVar(&data,copy);
printf("copied Data=%i",*copy);
}
现在问题是,"程序1"仍然成功编译,尽管警告了一些警告。但是编译程序2 GCC投掷错误:
错误:lVALUE要求为Unary'&amp;'操作数#Define copyvar(var,newvar)_generic((var),int:{{memcpy(newvar,(void) *)&amp; var,sizeof(int));}),
,我认为这是由于_generic int:选择再处理一个Ampersand
(void *)&amp;&amp; var
为什么GCC评估所有选择?
您的代码有各种问题:您将数据复制到一个非初始化的尖头,您的void* casts,您将 _Generic
视为某种复合语句,而不是表达式,等等。
但是要回答您的问题,您的代码不起作用,因为&something
的结果不是LVALUE。由于&
操作员需要一个LVALUE,因此您不能执行& &something
。(而且您不能进行&&something
,因为它被"最大蒙克规则"视为&amp; amp; amp; amp;
因此,您的代码与此代码不起作用的原因不起作用:
int x;
int**p = & &x;
GCC告诉您&x
不是LVALUE:
lvalue要求为Unary'&amp;'操作数
编辑 - 澄清
与任何宏一样,此_Generic
宏观像预处理器文本更换一样工作。因此,当您在宏中有此代码时:
_Generic((var), ...
int: ... (void *)&var
int*: ... (void)var
它被预先处理为
_Generic((&data), ...
int: ... (void *)& &data
int*: ... (void)&data
和_Generic
表达式的所有路径均已预处理。_Generic
本身不是预处理器的一部分,而是像任何包含运算符的表达式一样在以后进行评估。即使仅评估和执行该表达式的一部分,也会检查整个表达式的句法正确性。
_Generic
的缩进的原始用途与函数指针一样
#define copyVar(var,newVar)
_Generic((var),
int: function1,
int*: function2,
default:function3)(&(var), &(newVar))
在这里,通用表达式选择该函数,然后将此函数应用于参数。
您必须编写与三种不同情况相对应的三个存根功能。
如果您的标题文件中的inline
很小且不错,则优化器通常会确保此机构没有开销的运行时间。
这可以用两个级别_Generic
解决#define copyVar(var,newVar)
_Generic((var),
int : ({ __auto_type _v = var; memcpy(newVar, (void *) _Generic((_v), int: &_v , int *: _v) , sizeof(int));}) ,
int *: ({ __auto_type _v = var; memcpy(newVar, (void *) _v , sizeof(int));}) ,
default: newVar=var
)