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

Pie*_*ers 20 c printf

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

strcpy ( cTmpA, "hello" );
sprintf ( cTmpA, "%s world", cTmpA );
Run Code Online (Sandbox Code Playgroud)

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

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

Kor*_*icz 20

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

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


Aar*_*lla 9

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

你真的应该用snprintf()它来保护你免受缓冲区溢出.

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

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

#define sprintf(output,format,...) check_sprintf(__FILE__,__LINE__,output,format,....)
Run Code Online (Sandbox Code Playgroud)

请注意,并非所有编译器都支持使用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;   
}
Run Code Online (Sandbox Code Playgroud)

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