sprintf()的输入和输出字符串可以相同吗?

我在过去的代码中多次使用过这种类型的约定:

strcpy ( cTmpA, "hello" ); sprintf ( cTmpA, "%s world", cTmpA ); 

最近我将我的旧C编译器切换到Visual Studio 2005,发现我得到了一个由上面的代码产生的乱码。 然后我想到,sprintf()的行为可能没有严格定义,其中一个输入与输出字符串匹配。

以上代码是否有效K&R C? 如果没有,我如何在我的代码中找到sprintf()发生此类调用的所有位置?

虽然它是有效的K&R C,但您可能想要知道它是否是有效的POSIX – 请参阅sprintf规范 。 我们读:

如果由于调用sprintf()或snprintf()而在重叠的对象之间进行复制,则结果是未定义的。

sprintf()大多数实现都不复制格式字符串,而是在您传递的字符串中使用指针。 如果格式和输出指向同一个内存,那将导致奇怪的结果。

你应该使用snprintf()来保护你免受缓冲区溢出的影响。

要查找所有调用,请将#define sprintf +++放入公共标头查找并重新编译所有源。 这应该给你一个错误列表以及文件名和行号:)或者使用你的IDE的递归搜索。

如果要将此列表修剪为对两个参数使用相同指针的列表,请使用此宏:

 #define sprintf(output,format,...) check_sprintf(__FILE__,__LINE__,output,format,....) 

请注意,并非所有编译器都支持使用varargs的宏。 然后定义一个新函数check_sprintf

 int check_sprintf (char*filename,int line,char*output,char*format,...) { va_list args; int len; if(output==format) { fprintf(stderr, "Output and format are the same at %s:%d", filename, line); abort(); } va_start (args, format); len = vsprintf (output, format, args); va_end (args); return len; } 

[编辑]我刚刚看到你在谈论输出和第一个参数。 您可以重用上面的代码并调用va_arg()来获取第一个参数并在比较中使用它。