带有 _Generic 的奇怪 gcc 警告

2023-12-27

我有一些代码根据参数的类型使用 _Generic 来调度函数。我不明白 gcc 生成的警告。

编译用gcc main.c

#include <stdio.h>

#define FOOBAR(x) _Generic((x),  \
  int *: foo(x),                  \
  long *: bar(x)                  \
)

void foo(int* x) {
    printf("foo\n");
}

void bar(long* y) {
    printf("bar\n");
}

int main() {
    int a = 1111;
    long b = 2222;

    FOOBAR(&a);
    FOOBAR(&b);
}

现在,这段代码确实可以编译并且 _Generic 按预期工作,即“foo”出现然后“bar”。然而,编译器(gcc 和 clang)生成一个奇怪的警告,看起来它会将 _Generic 的参数匹配到错误的行:

main.c: In function ‘main’:
main.c:20:12: warning: passing argument 1 of ‘bar’ from incompatible pointer type [-Wincompatible-pointer-types]
   20 |     FOOBAR(&a);
      |            ^~
      |            |
      |            int *
main.c:5:15: note: in definition of macro ‘FOOBAR’
    5 |   long *: bar(x)                \
      |               ^
main.c:12:16: note: expected ‘long int *’ but argument is of type ‘int *’
   12 | void bar(long* y) {
      |          ~~~~~~^
main.c:21:12: warning: passing argument 1 of ‘foo’ from incompatible pointer type [-Wincompatible-pointer-types]
   21 |     FOOBAR(&b);
      |            ^~
      |            |
      |            long int *
main.c:4:14: note: in definition of macro ‘FOOBAR’
    4 |   int *: foo(x),                \
      |              ^
main.c:8:15: note: expected ‘int *’ but argument is of type ‘long int *’
    8 | void foo(int* x) {
      |          ~~~~~^

生成两个警告,每个 FOOBAR 一个。似乎正在过去&a这是 int * 到 bar 需要一个 long *,反之亦然&b。 (注释掉 FOOBAR 之一即可看到一个不兼容的指针错误。)

为什么 gcc 警告我 _Generic 正在将其参数分派给错误的函数?


我知道这通常不是人们使用 _Generic 的方式,即参数列表通常是outside_Generic()。但我有一些用于分派到采用不同数量参数的函数的用例。


请注意标准中的示例§6.5.1.1 通用选择 http://port70.net/%7Ensz/c/c11/n1570.html#6.5.1.1 is:

5 示例 cbrt 类型通用宏可以按如下方式实现:

 #define cbrt(X) _Generic((X),                             \
                         long double: cbrtl,               \
                         default: cbrt,                    \
                         float: cbrtf                      \
                         )(X)

请注意函数调用的括号所在的位置 - 在_Generic(…)通用选择的一部分。

将其调整为您的代码:

#include <stdio.h>

#define FOOBAR(x) _Generic((x),           \
                           int *:  foo,   \
                           long *: bar    \
                           )(x)

static void foo(int *x)
{
    printf("foo (%d)\n", *x);
}

static void bar(long *y)
{
    printf("bar (%ld)\n", *y);
}

int main(void)
{
    int a = 1111;
    long b = 2222;

    FOOBAR(&a);
    FOOBAR(&b);

    return 0;
}

这可以使用 GCC 10.2.0 set fussy 干净地编译(源文件gs31.c):

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -fno-common -c gs31.c
$

代码在外部发生变化FOOBAR宏避免我的标准编译选项请求的编译警告。

代码的 C 预处理器的输出是:

int main() {
    int a = 1111;
    long b = 2222;

    _Generic((&a), int *: foo(&a), long *: bar(&a) );
    _Generic((&b), int *: foo(&b), long *: bar(&b) );
}

和....相比:

int main(void)
{
    int a = 1111;
    long b = 2222;

    _Generic((&a), int *: foo, long *: bar )(&a);
    _Generic((&b), int *: foo, long *: bar )(&b);
}

区别在于您的代码调用foo() with a long * (aka &b) and bar()int * (aka &a),这就是(正确地)触发警告的原因。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有 _Generic 的奇怪 gcc 警告 的相关文章

随机推荐

  • Clang 构建非常慢并且中途挂起

    我正在开始编写自己的 clang 工具 这些是我到目前为止所遵循的步骤 查看 llvm 7 0 发行版 查看 clang 7 0 版本 建造 使用带有以下标志的 ninja 构建 clang 和 llvm 没有这些标志就一直挂在我身上 DL
  • 产量有限制的子组合

    我正在使用 python 3 我正在使用的函数如下 def sub combinations segment if len segment 1 yield segment else for j in sub combinations seg
  • 在 Swift 包管理器中添加对二进制目标的依赖项

    我想创建一个带有具有子依赖项的二进制目标的 Swift 包 由于二进制目标不支持开箱即用的子依赖项 因此我创建了一个包装器目标 该目标既依赖于二进制框架又依赖于所述的其他依赖项here https stackoverflow com a 6
  • 如何将 NSNumber 转换为 NSString

    所以我有一个NSArray myArray 与NSNumbers and NSStrings 我需要它们在另一个UIView所以我就这样 void tableView UITableView tableView didSelectRowAt
  • 将div类中的信息提取到json对象(或数据框)

    对于表中的每一行页面 我想单击 ID 例如 第 1 行的 ID 是 270516746 并将信息 每行没有相同的标题 提取 下载到某种形式的 python 对象中 最好是 json 对象 或数据框 json 可能更容易 我已经到了可以到达我
  • “CHOICE_MODE_MULTIPLE_MODAL”网格视图的最大可选数量

    我创建了一个 GridviewCHOICE MODE MULTIPLE MODAL在安卓中 一切都运转良好 但根据要求 我必须为可选项目设置限制 假设 gridview 的最大可选项目限制是 3 个项目 达到限制后 用户无法再选择并会显示一
  • 为 Windows CE 编译 Boost 1.47

    实际上有一些关于人们尝试为 Windows CE 构建 Boost 库的信息 但没有人报告成功 甚至没有给出这样做所需的步骤 对于两个最新版本 1 46 和 1 47 发行说明提到他们的测试编译器之一是 Visual C Windows M
  • 如何在Python中检查EOF? [复制]

    这个问题在这里已经有答案了 如何在 Python 中检查 EOF 我在代码中发现了一个错误 其中分隔符后的最后一个文本块未添加到返回列表中 或者也许有更好的方式来表达这个功能 这是我的代码 def get text blocks filen
  • JQuery 透视对话框覆盖

    有几个 JQuery 插件可以放置模式对话框并在对话框中显示 dom 元素 但我正在寻找一个对话框叠加层 它可以显示屏幕的某些部分 并且这些区域应该是可访问的 而其他元素应该被阻止 我已经整理了一个简单的插件来执行此操作 不确定您的要求范围
  • 在 matplotlib 中绘制 unix 时间戳

    我想用 python 的 matplotlib 模块制作一个通用值与时间图 我的时间是 unix 时间 但我希望它们以可读的格式显示在绘图的 x 轴上 我已阅读有关使用日期时间对象进行绘图的答案 但此方法似乎删除了小时 分钟 秒信息和全天的
  • Hibernate 和 JPA“mappedBy”与关系和级联的所有者

    背景 假设我们有双向OneToOne关系 有User and Address实体 User有很多Addresses CREATE SEQUENCE IF NOT EXISTS hibernate sequence CREATE TABLE
  • 使用 Jquery 插件提交表单时如何验证“.(点)”后的电子邮件

    我正在尝试验证一个表单 该表单的电子邮件地址的 prop 设置为 true 如下所示 myform validate rules field required true email true 我检查了 jquery 插件http jquer
  • 如何在 mxGraph 中使用曲线边缘样式

    mxGraph 的最新版本添加了曲线作为边缘样式 我预计这是一种边缘路由风格 但事实似乎并非如此 谁能给我展示一个带有弯曲边缘的图表的小例子吗 它实际上是边缘的形状样式 style graph getStylesheet getDefaul
  • 本地测试时如何轻松启用azure功能https

    我想在 Windows 上本地测试 Azure Function Http 触发器 我使用 azure function core tools 运行命令 例如func start port 5007 useHttps 然后我收到错误 自动证
  • 在 Mobile Safari 下拉列表项选择框中使用“下一步”时,select/dropdown 的 onchange() JS 事件的奇怪行为

    这是一个很难说清楚的问题 而且我是移动网络开发的新手 所以请耐心听我说 在我的网页上 我有 3 个嵌套下拉列表 区域 城镇 街道 嵌套如下 当其上方的下拉列表中的选择发生更改时 每个下拉列表的项目都会被修改 例如选择一个Area改变了Tow
  • 反应图标应用线性渐变

    我想使用线性渐变动态地部分填充来自反应图标的 Font Awesome Star 我已经尝试过以下方法 具有内联样式的 React 组件 将父跨度的背景设置为渐变并使 SVG 透明 似乎无法将 SVG 星形周围的边框设置为 FFFFFF 因
  • 如何使用 jquery 将 LI 的项目转换为 json 对象?

    如果我有一个如下所示的列表 ul class nameList li value Bob li li value Frank li li value Sally li ul 我如何将其转换为 json 对象 如下所示 id 1 title
  • React:将焦点添加到作为包装器的组件的第一个子级

    如果我有一个像这样的组件 const Comp children gt some code return div children div 然后这样称呼它
  • node-mysql:多语句查询,ER_PARSE_ERROR

    我正在尝试对 MySQL 数据库运行多语句查询 我正在使用 node mysql 和 ExpressJS 我通过将 multipleStatements 设置为 true 启用了多语句查询 const connection mysql cr
  • 带有 _Generic 的奇怪 gcc 警告

    我有一些代码根据参数的类型使用 Generic 来调度函数 我不明白 gcc 生成的警告 编译用gcc main c include