c++ 什么是G_STMT_START和G_STMT_END?

2nbm6dog  于 2022-12-20  发布在  其他
关注(0)|答案(3)|浏览(309)

我正在将一些代码从GIMP source code base移植到我正在编写的程序中。(/gimp-2.8.10//modules/display-filter-color-blind.c)引用名为GIMP_CAIRO_ARGB32_SET_PIXEL的宏(gimp-2.8.10//libgimpcolor/gimpcairocolor.h).在这个宏中有一个叫做G_STMT_START/G_STMT_END的东西。(Mac OSX通过Xcode使用默认编译器)抱怨错误“使用未声明的标识符”G_STMT_START“”我知道这不是宏放置位置的范围问题(在名为globals. h的头文件中,我将其包含在my .h中),因为编译器没有抱怨GIMP_CAIRO_ARGB32_SET_PIXEL定义。
有人知道这里发生了什么吗?我尝试过在GIMP源代码中搜索G_STMT_START的所有示例,但没有找到任何定义G_STMT_START/G_STMT_END的东西。我还在GIMP工具包文档中找到了某种解释,但它远远没有帮助(至少对我来说)。
这是我尝试使用的完整宏:

/**
 * GIMP_CAIRO_ARGB32_SET_PIXEL:
 * @d: pointer to the destination buffer
 * @r: red component, not pre-multiplied
 * @g: green component, not pre-multiplied
 * @b: blue component, not pre-multiplied
 * @a: alpha component
 *
 * Sets a single pixel in an Cairo image surface in %CAIRO_FORMAT_ARGB32.
 *
 * Since: GIMP 2.6
 **/
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define GIMP_CAIRO_ARGB32_SET_PIXEL(d, r, g, b, a) \
  G_STMT_START {                                   \
    const guint tr = (a) * (r) + 0x80;             \
    const guint tg = (a) * (g) + 0x80;             \
    const guint tb = (a) * (b) + 0x80;             \
    (d)[0] = (((tb) >> 8) + (tb)) >> 8;            \
    (d)[1] = (((tg) >> 8) + (tg)) >> 8;            \
    (d)[2] = (((tr) >> 8) + (tr)) >> 8;            \
    (d)[3] = (a);                                  \
  } G_STMT_END
#else
#define GIMP_CAIRO_ARGB32_SET_PIXEL(d, r, g, b, a) \
  G_STMT_START {                                   \
    const guint tr = (a) * (r) + 0x80;             \
    const guint tg = (a) * (g) + 0x80;             \
    const guint tb = (a) * (b) + 0x80;             \
    (d)[0] = (a);                                  \
    (d)[1] = (((tr) >> 8) + (tr)) >> 8;            \
    (d)[2] = (((tg) >> 8) + (tg)) >> 8;            \
    (d)[3] = (((tb) >> 8) + (tb)) >> 8;            \
  } G_STMT_END
#endif

谢谢你的帮助!

k7fdbhmy

k7fdbhmy1#

我也不知道这可能是什么(尽管现在我知道了,我告诉自己我可能已经猜到了),但要找到答案所需要的只是在Google中输入G_STMT_START并点击the first result
这一页是Glib手册中的文档,它揭示了这是一个专为在多语句宏中使用而设计的宏。

一米一分一秒

#define     G_STMT_START

在多语句宏中使用,以便可以在编译器只需要一个语句的地方使用它们。

G_STMT_END

#define     G_STMT_END

在多语句宏中使用,以便可以在编译器只需要一个语句的地方使用它们。
稍后在搜索结果中,您将获得gmacros.h头文件的一个或多个副本,这些宏实际上是在其中定义的:

/* Provide simple macro statement wrappers (adapted from Perl):
 *  G_STMT_START { statements; } G_STMT_END;
 *  can be used as a single statement, as in
 *  if (x) G_STMT_START { ... } G_STMT_END; else ...
 *
 *  For gcc we will wrap the statements within `({' and `})' braces.
 *  For SunOS they will be wrapped within `if (1)' and `else (void) 0',
 *  and otherwise within `do' and `while (0)'.
 */
#if !(defined (G_STMT_START) && defined (G_STMT_END))
#  if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
#    define G_STMT_START    (void) __extension__ (
#    define G_STMT_END      )
#  else
#    if (defined (sun) || defined (__sun__))
#      define G_STMT_START  if (1)
#      define G_STMT_END    else (void)0
#    else
#      define G_STMT_START  do
#      define G_STMT_END    while (0)
#    endif
#  endif
#endif

由此可以很清楚地看出,这些宏只是实现了the standard idiom,除了在GCC上,它们使用的扩展正是为此目的而设计的。
我认为GIMP代码中还有其他部分依赖于Glib头文件,所以如果你使用它的代码,你可能会想把它们包括进来,但如果没有,这里有足够的信息来实现代码的相关部分。

qhhrdooz

qhhrdooz2#

G_STMT_STARTG_STMT_END是gimp所依赖的Gnome Glib库中的宏。
它们在gmacros.h中定义。

qnyhuwrf

qnyhuwrf3#

目前,GTK 4 - GLib 2.0的文档不再包括G_STMT_STARTG_STMT_END等其他宏。如果您查看来自geany或Web归档等其他来源的旧文档,可以看到它们被定义为

#define G_STMT_START  do
#define G_STMT_END    while (0)

实际上,在<glib/gmacros.h>(对于GLib 2.0)中,真实的的定义是:

#if !(defined (G_STMT_START) && defined (G_STMT_END))
#define G_STMT_START  do
#if defined (_MSC_VER) && (_MSC_VER >= 1500)
#define G_STMT_END \
    __pragma(warning(push)) \
    __pragma(warning(disable:4127)) \
    while(0) \
    __pragma(warning(pop))
#else
#define G_STMT_END    while (0)
#endif
#endif

它只是封装了一个do ... while(0)块。Cody Gray的回答很好地介绍了这个宏对的效果-标准的习惯用法。

相关问题