linux - Wie drucke ich mit snprintf den ursprünglichen Inhalt und einige neue Inhalte in ein Array?
仅有的幸福
仅有的幸福 2017-05-27 17:44:46
0
1
883

snprintfDiese Funktion erfordert eine angegebene Länge und der Compiler führt eine Überprüfung außerhalb der Grenzen durch. Daher muss sichergestellt werden, dass die Ziellänge länger als die Summe aller Parameter ist. Beachten Sie jedoch die folgenden Vorgehensweisen:

#include <stdio.h>
#include <string.h>

#define LENGTH 1024

int main() {
    char cache[LENGTH];
    memset(cache, 0, LENGTH);
    snprintf(cache, sizeof(LENGTH), "%s/ruaruarua", cache);
    return 0;
}

Nach dem Öffnen dieses Programms-Wall wird ein Fehler gemeldet:

test.c: In function ‘main’:
test.c:9:44: error: ‘/ruaruarua’ directive output truncated writing 10 bytes into a region of size 4 [-Werror=format-truncation=]
     snprintf(cache, sizeof(LENGTH), "%s/ruaruarua", cache);
                                        ~~~~^~~~~~
test.c:9:5: note: ‘snprintf’ output 11 or more bytes into a destination of size 4
     snprintf(cache, sizeof(LENGTH), "%s/ruaruarua", cache);
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors

Dieser Fehler ist zu erwarten, da es tatsächlich möglich ist, die Grenze zu überschreiten. Die Frage ist also: Wie kann ich dieselbe Funktion ausführen, ohne einen Fehler zu melden?

Meingcc版本比较新,7.1.1, es wird geschätzt, dass ältere Versionen des Compilers diesen Fehler nicht melden.

仅有的幸福
仅有的幸福

Antworte allen(1)
洪涛

首先snprintf()的第二个参数代表的是缓冲区的大小,在这里应该是LENGTHsizeof(LENGTH)的值是4
(我猜你想写的应该是sizeof(cache)吧)。那么,改成snprintf(cache, LENGTH, "%s/ruaruarua", cache);之后就行了吗?我们看看这个例子:

#include <stdio.h>

int main()
{
    char buf[20] = "hello";
    snprintf(buf, 20, "%s world", buf);
    puts(buf);
    return 0;
}

这个例子企图给buf末尾添加一个字符串,看看输出


 world

并没有达到期望的结果。这是为什么呢?snprintf()的手册里有这么一段:

Some programs imprudently rely on code such as the following

sprintf(buf, "%s some further text", buf);

to append text to buf. However, the standards explicitly note that the results are undefined if source and destination buffers overlap when calling sprintf(), snprintf(), vsprintf(), and vsnprintf(). Depending on the version of gcc(1) used, and the compiler options employed, calls such as the above will not produce the expected results.

即如果原始和目标缓冲区重叠的话,这些printf()家族的函数执行结果将是未定义的。

那该如何如何“向一个数组中打印自己原有的内容和一些新的内容”呢?一种方式是把传给snprintf()的缓冲区设为数组中字符串的末尾:

snprintf(buf + strlen(buf), 20, " world");

那如何连续往缓冲区末尾添加数据呢?注意到printf()家族的函数返回值都是打印的字符数(number of characters printed),那么可以这么调用:

#include <stdio.h>
#include <string.h>

int main()
{
    char buf[40];
    char *p = buf;

    p += sprintf(p, "hello %s\n", "world");
    p += sprintf(p, "hello %s", "again");
    /* and more similar calls... */

    puts(buf);
    return 0;
}

结果为

hello world
hello again
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage