You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用__builtin_va_arg_pack()编译失败,如何排查解决?

链接错误:undefined reference to myprintf 原因及解决

问题场景

出于纯教学目的,尝试使用GCC的「构造函数调用内置函数」编写示例,实现代码如下:

#include <stdio.h>

extern int myprintf(FILE *f, const char *format, ...);
extern inline __attribute__((__gnu_inline__)) int myprintf(FILE *f, const char *format, ...)
{
    int r = fprintf(f, "myprintf: ");
    if (r < 0)
        return r;
    int s = fprintf(f, format, __builtin_va_arg_pack());
    if (s < 0)
        return s;
    return r + s;
}
int main()
{
    myprintf(stdout, "ciao %d\n", 10);
    return 0;
}

执行编译命令gcc -std=gnu2x -Wall test1.c -o test1时,出现链接错误:

/usr/bin/ld: /tmp/ccgD1BYT.o: in function `main':
test1.c:(.text+0x27): undefined reference to `myprintf'
collect2: error: ld returned 1 exit status

使用GCC版本为Ubuntu 13.2.0-4ubuntu3。

问题原因

问题出在extern inline与__gnu_inline__属性的组合逻辑上:

  • 当使用extern inline __attribute__((__gnu_inline__))时,GCC遵循GNU扩展的inline规则:编译器只会尝试将该函数内联到调用处,不会在当前编译单元生成该函数的外部可见定义,而是假设这个函数的定义会在其他编译单元中提供。
  • 但代码中仅提供了这一个inline版本的实现,没有其他地方的非inline定义,因此链接器找不到myprintf的符号,抛出未定义引用错误。

解决方法

方法1:移除extern关键字

去掉函数声明和定义中的extern,仅保留inline __attribute__((__gnu_inline__)),这样GCC会在当前编译单元中生成该函数的本地定义(当无法内联时),同时支持内联展开:

#include <stdio.h>

inline __attribute__((__gnu_inline__)) int myprintf(FILE *f, const char *format, ...)
{
    int r = fprintf(f, "myprintf: ");
    if (r < 0)
        return r;
    int s = fprintf(f, format, __builtin_va_arg_pack());
    if (s < 0)
        return s;
    return r + s;
}

int main()
{
    myprintf(stdout, "ciao %d\n", 10);
    return 0;
}

方法2:保留extern并补充外部定义

如果需要保留extern inline的写法,需要单独提供一个非inline的myprintf实现(可以放在同一个文件或其他编译单元),例如:

#include <stdio.h>

// 声明+inline定义
extern int myprintf(FILE *f, const char *format, ...);
extern inline __attribute__((__gnu_inline__)) int myprintf(FILE *f, const char *format, ...)
{
    int r = fprintf(f, "myprintf: ");
    if (r < 0)
        return r;
    int s = fprintf(f, format, __builtin_va_arg_pack());
    if (s < 0)
        return s;
    return r + s;
}

// 补充外部定义
int myprintf(FILE *f, const char *format, ...)
{
    int r = fprintf(f, "myprintf: ");
    if (r < 0)
        return r;
    int s = fprintf(f, format, __builtin_va_arg_pack());
    if (s < 0)
        return s;
    return r + s;
}

int main()
{
    myprintf(stdout, "ciao %d\n", 10);
    return 0;
}

内容的提问来源于stack exchange,提问作者mastupristi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 18:02:40