我正在查看IDE中包含的math.h标头.我看到以下代码是我不理解的语法.这是基本的东西,但有人可以向我解释这是如何工作的吗?
#define isgreater(x,y) \
(__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
!isunordered(__x,__y) && (__x > __y);}))
Run Code Online (Sandbox Code Playgroud)
那么例如当你用双下划线开始时它会做什么,例如:__typeof
是否允许未定义的大小?所以这个宏可以采用不同大小的值?
斜线只是跨越源中的换行符吗?
怎么__extension__办?
谢谢
您正在使用一些编译器扩展:
__typeof__是一个GCC扩展,它允许您获取变量的类型(并在变量声明中使用它); 它存在,以便宏可以处理任何类型x和y.({ ... })一个表达式,计算结果中的最后一个语句的值 ; 这允许您在此块中声明变量,这是为了避免评估两个操作数x和y两次.结果x和y(这可能是像i++你不想评价两次)存储在两个临时变量__x和__y,然后这两个临时变量,而不是使用x和y避免双重评价.__extension__ 是一个扩展,它会抑制您使用上述扩展程序获得的警告.是的,\只是使宏的定义跨越多行(\将行连接在一起并在编译过程中很早就完成,甚至在查看宏和预处理器定义之前).
这个严峻的要点是避免评估x和y两次.如果你这样做了
bool g = isgreater(x++, y++);
Run Code Online (Sandbox Code Playgroud)
你没有使用那个技巧,你会得到
bool g = !isunordered(x++, y++) && (x++ > y++);
Run Code Online (Sandbox Code Playgroud)
这将导致x和y增加两次,而不是像你想象的那样只增加一次.相反,通过这个技巧,你可以获得类似的东西(为临时变量使用更好的名称)
int tmpx = x++;
int tmpy = y++;
bool g = !isunordered(tmpx, tmpy) && (tmpx > tmpy);
Run Code Online (Sandbox Code Playgroud)
(如果是x和y整数)这是正确的,并避免双增量.这也适用于其他事情,例如函数调用:
isgreater(launch_missiles(3), launch_missiles(4));
Run Code Online (Sandbox Code Playgroud)
没有技巧,你最终会发射14枚导弹而不是7枚,这将是灾难性的.