关于C#:sprintf_s()隐式声明警告

sprintf_s() implicit declaration warning

我有一个C代码,其中有此行。

1
sprintf_s(var, outfile_ppm, local_filecounter++);

在此,varchar*类型,local_filecounterint类型。

当我运行代码时,它发出以下警告:

warning: implicit declaration of function 'sprintf_s' is invalid in C99 [-Wimplicit-function-declaration]

这是什么警告,我该如何消除它?


sprintf_s函数是附件K / TR 24731边界检查接口的一部分。但是,对这些接口感兴趣的任何人都应阅读N1967附录K"边界检查接口"的现场经验。这是节选:

Despite more than a decade since the original proposal and nearly ten years since the ratification of ISO/IEC TR 24731-1:2007, and almost five years since the introduction of the Bounds checking interfaces into the C standard, no viable conforming implementations has emerged. The APIs continue to be controversial and requests for implementation continue to be rejected by implementers.

确实,如果您查看GCC C11状态页面,将会看到(强调):

Bounds-checking (Annex K) [Optional]: Library issue (not implemented)

附件K的唯一主要实现(sprintf_s和其他类似功能的_s版本)在Visual Studio中。给出的流行解释是,这些函数由Microsoft内部使用,以其自己的代码库内部来解决安全问题。

其他实现依赖于Valgrind,mudflap,地址清理器等工具来解决同一组问题,并且Microsoft之外很少有代码库实际使用这些功能,因此实现它们的动力很小。

换句话说,如果您不使用Visual Studio,则不能使用这些功能。幸运的是,它们不是必需的。

问题中对sprintf_s的调用很可能始于……

1
2
// Wait, what? Something smells fishy...
sprintf_s(var, outfile_ppm, local_filecounter++);

sprintf_s的第三个参数应该是格式字符串,但是local_filecounter++看起来太可疑了,无法成为格式字符串。

通常,您将使用snprintf(会截断其输出以适合缓冲区),或者使用asprintf(如果可以使用C标准以外的函数)。

1
2
char var[256];
snprintf(var, sizeof(var), outfile_ppm, localfile_counter++);

请注意,如果var没有数组类型,则不能使用sizeof(var)来计算其大小,此处有关用作函数参数时会衰减到指针的数组的常见警告适用于此。

摘要:除非切换到Visual Studio或自己实现,否则不能使用sprintf_s()。坚韧的饼干。

次要说明:理论上,如果需要sprintf_s,则应定义__STDC_WANT_LIB_EXT1__。但是,实际上,唯一定义了sprintf_s的主要实现都是这样做,而与宏的存在无关(据我所知)。事情可能已经改变。