【问题标题】:Using snprintf with C90将 snprintf 与 C90 一起使用
【发布时间】:2021-12-14 21:47:54
【问题描述】:

有没有办法指示编译器:

  • 语言是 C90
  • stdio.h 的声明是 C99(包括 snprintf)的声明

使用cc -std=c90 -Wall(在使用 snprintf 的源文件上)会发出烦人的警告(有时,取决于编译器/环境,会出现令人困惑的提示,即应该包含 stdio.h,即使它已经包含在内),但是链接器还是找到了 snprintf 。我明白发生了什么,这不是问题。

使用 strict c90(语言)和 snprintf(库函数)在技术上是可行的,但我不知道如何相应地指导编译器。换句话说,我想区分语言合规性和图书馆合规性。

备注:我假设 C99 stdio.h 头文件中使用的语言实际上是 C90,因此它可以包含在 C90 源文件中。有什么能阻止它吗?

为了可移植性,我更喜欢使用通用 include <stdio.h> 的解决方案。

【问题讨论】:

  • 我不知道 C89 和 C99 之间发生的所有变化,但 C99-stdio.h 甚至会是与 C89 兼容的语言吗?
  • 问:是否有一些神奇的编译器开关可以强制您的“用户代码”符合 C90,但您包含的标头符合 C99?答:不存在,也不可能。问:C99 版本的“stdio.h”会以某种方式违反 C90 合规性吗?答:不会。 问:为符合 C90 标准而编译的“用户代码”是否会与 C99 版本的 C 运行时库不兼容?答:不会。 问:用旧的 C90 编译器编译的“用户代码”是否会与 C99 版本的 C 运行时库不兼容? A:我怀疑,但有可能……
  • 这是否可行以及如何实现取决于您的实施,因此我无法给出正确答案。但是,请查看“功能选择宏”和/或“功能测试宏”的文档。
  • @StephenNewell C99-stdio.h 可以很好地用 C90 和 C99 的通用集合编写,也就是说,直到旧的构造(例如隐式 int),都非常接近 C90。 C99本质上是C90的扩展,我猜C99标准库的很多功能都不需要扩展。

标签: c header-files c99 stdio c89


【解决方案1】:

是的,虽然这样做有点奇怪。

您可以定义 _ISOC99_SOURCE 来表示您希望定义 C99 函数。

例子:

#define _ISOC99_SOURCE
#include <features.h>
#include <stdio.h>

int main() {
    char buf[10];
    snprintf(buf, 4, "foo");
    puts(buf);
    return 0;
}

像这样编译它:

$ gcc -std=c90 -Wall test.c  
$ ./a.out 
foo

这适用于 gcc 10.3.0 和 clang 11.0.0。在库兼容性方面,只用glibc测试过,没有用musl或其他版本的标准库测试过。

【讨论】:

  • 谢谢。这就是我一直在寻找的。我不认为这很奇怪,许多代码分析工具在 C90 上效果最好,但 C99 的一些库函数(如 snprintf)很有用。
  • 它也适用于 cygwin (gcc 10.2.0)。有趣的是,在 linux 下 features.h 不是必需的,但在 cygwin 下是必需的。
  • @Loic 与 glibc, features.h 自动包含在每个公共标头中,但不打算直接包含(如果我们要重新做一遍,我们可能会将它放在“位”子目录)。我很惊讶 cygwin 要求你直接包含它。
  • @zwol 很有趣,谢谢。我看到 stdio.h 包含 features.h,但我认为这是库用户不应该依赖的实现细节。
  • @NickODell 你的假设对 glibc 是正确的,我不知道 cygwin
【解决方案2】:

没有。

用于 C90 编译器的通用 #include &lt;stdio.h&gt; 不需要声明 snprintf

在您争辩说它不是 C90 编译器之前,请记住您要求它充当一个 usng -std=c90。充当 C90 编译器的编译器不需要做 C90 编译器不会做的任何事情。

因此没有通用的解决方案。

可能有特定于编译器的解决方案,包括添加以下内容:

int snprintf( char * buffer, size_t bufsz,  const char * format, ... );

【讨论】:

  • 无需手动声明即可在 GCC 上工作。可能是因为 c90 不需要声明 gcc.godbolt.org/z/r7joY1Gao
  • @Ayxan Haqverdili,嗯,我今天只收到一个没有声明的警告,但昨天我收到了一个错误。但问题是关于-Wall 产生的警告。
  • 另一方面,snprintf 没有做任何在用户代码函数中无法完成的事情,该函数可以移植,除非需要知道长度的上限实现的printf 函数的%p 格式说明符可能输出的文本。
猜你喜欢
  • 2013-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-02
相关资源
最近更新 更多