【问题标题】:I have not included the <unistd.h> header file, why can I still invoke the getpid() function successfully?我没有包含 <unistd.h> 头文件,为什么我仍然可以成功调用 getpid() 函数?
【发布时间】:2020-02-09 00:31:11
【问题描述】:

代码如下:

int main (int argc, char *argv[]) {
    long pid = (long)getpid();
    long test = pid + 1;
}

没有包含任何头文件,仍然可以成功编译代码,仍然可以成功运行程序。

为什么?

环境信息:Ubuntu 18.04.2 LTS、gcc (Ubuntu 4.8.5-4ubuntu8) 4.8.5

【问题讨论】:

  • 这意味着您使用的是旧版本的 GCC(默认为 C90 而不是 C11 模式)并且没有使用足够的编译器警告选项。
  • 请注意,当您的代码不使用任何命令行参数时,最好使用int main(void)。优化器可以消除 main() 函数的主体,而不会改变程序的可见行为。

标签: c linux


【解决方案1】:

没有包含任何头文件,
仍然可以成功编译代码。
仍然可以成功运行程序。
为什么?

为什么不呢?

尽管存在特定代码是否符合语言标准的所有问题,但语言不符合并不意味着编译或执行一定会失败。相反,您会得到未定义的行为,它可以在机器的生产能力范围内以任何方式表现出来,包括成功编译和按预期运行。

但是,在您的特定情况下,您使用的是 GCC 4.8.5。 GCC 4.8 系列默认编译为 C90 标准,带有 GNU 扩展。 C90 允许在没有范围内声明的情况下调用函数,以与早期的预标准化实践兼容。这在 C99 或更高版本中不再允许,但许多实现仍然继续接受它作为扩展。

然而,应该理解的是,当被调用函数具有范围内原型时,C 对某些参数列表的解释与没有时不同(即使对于 的函数也是如此> 声明,因为并非所有声明都提供原型)。在某些情况下,您也许可以避免调用未声明的函数,但它的风格很差,如果您做得足够好,那么它在某些时候咬你。

还要注意,即使在 C90 或 GNU90 模式下编译时,GCC 4 也绝对能够发出有关使用情况的警告,例如您的。您最好在编译时打开-Wall 选项,也可以打开其他警告选项。

【讨论】:

    【解决方案2】:

    通常,要使用动态库函数,您必须在编译时通过-l 开关链接到指定的库,例如使用数学函数时的gcc -lm prog.c(来自libm)。

    但是,由于它很常见,GCC 总是默认链接标准 C 库,这意味着执行 gcc prog.c 实际上与执行 gcc -lc prog.c 相同。无论您是否包含任何标题,这始终会完成。

    使这项工作起作用的第二件事是,GCC 假定任何在编译时尚未声明的函数都具有签名int func(void)。在这种情况下,签名与真正的getpid() 函数非常相似。

    如果您使用ldd 工具查看您编译的程序以显示需要哪些动态库,您会看到该程序与libc 链接:

    $ ldd prog
        linux-vdso.so.1 (0x00007ffede7d0000)
    ==> libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0f47018000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0f475b9000)
    

    当您的程序运行时,它会在第一次调用之前询问动态加载程序在哪里(在哪个地址)找到getpid 函数。动态加载程序检查加载的库,并在 libc 中找到具有该名称的函数,因此一切似乎都可以正常工作没有问题。

    默认情况下,您可以使用-nostdlib 编译器开关告诉 GCC 不链接到标准库,但这在您的情况下没有那么有用。真正的解决方案是始终将有关隐式函数声明的警告视为错误 (-Werror=implicit-function-declaration)。

    如果您的编译器默认没有给出此警告,我建议您将其升级到较新的版本。 GCC 4 绝对不是适用于 Ubuntu 18 的最新版本。

    $ sudo apt update
    $ sudo apt upgrade
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-30
      • 1970-01-01
      • 2014-09-08
      • 2015-05-18
      • 2017-02-25
      • 2017-02-17
      • 2021-03-31
      • 1970-01-01
      相关资源
      最近更新 更多