基本C头文件语法

时间:2012-03-19 18:48:05

标签: c header-files

我正在查看IDE中包含的math.h标头。我看到以下代码是我不理解的语法。这是基本的东西,但有人可以向我解释这是如何工作的吗?

#define isgreater(x,y) \
          (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
                           !isunordered(__x,__y) && (__x > __y);}))

例如,当您开始使用双下划线时,它会做什么,例如:__typeof 是否允许不确定的尺寸?所以这个宏可以采用不同大小的值吗?

斜线只是跨越源中的换行符吗?

__extension__做了什么?

感谢

2 个答案:

答案 0 :(得分:8)

您正在使用一些编译器扩展:

  • __typeof__是一个GCC扩展,它允许您获取变量的类型(并在变量声明中使用它);它存在,以便宏可以处理任何类型xy
  • 第二个GCC扩展将({ ... })转换为表达式,该表达式计算为其中最后一个语句的值;这允许您在此块中声明变量,这是为了避免两次评估两个操作数xyxy的结果(可能类似i++,您不想要评估两次)存储在两个临时变量__x和{ {1}}然后使用这两个临时变量而不是__yx来避免双重评估。
  • y是一个扩展程序,可以抑制您使用上述扩展程序时发出的警告。

是的,__extension__只是使宏跨度的定义多行(\将行连接在一起,并且在编译过程中很早就完成了,甚至在查看宏和预处理器定义之前在)。

这个严峻的要点是避免两次评估\x。如果你做了

y

你没有使用这个技巧,你得到了

bool g = isgreater(x++, y++);

这会导致bool g = !isunordered(x++, y++) && (x++ > y++); x每次增加两次,而不是像您预期的那样增加一次。相反,通过这个技巧,你可以获得类似的东西(使用更好的临时变量名称)

y

(如果int tmpx = x++; int tmpy = y++; bool g = !isunordered(tmpx, tmpy) && (tmpx > tmpy); x是整数)这是正确的,并避免双增量。这也适用于其他事情,例如函数调用:

y

如果没有技巧,你最终会发射14枚导弹而不是7枚,这将是灾难性的。

答案 1 :(得分:3)

重新格式化定义可能对您有所帮助

#define isgreater(x,y)                        \
(                                             \
  __extension__ (                             \
    {                                         \
      __typeof__(x) __x = (x);                \
      __typeof__(y) __y = (y);                \
      !isunordered(__x,__y) && (__x > __y);   \
    }                                         \
  )                                           \
)

__extension__标记使用gcc扩展到标准ANSI C的代码。在这种情况下的扩展是__typeof__运算符,它在编译时提供变量的类型,并用于声明{ {1}}和__x__yx的类型相同。然后继续检查这对值是否有序y是数学库函数)并且isunordered大于__x