Maison > Questions et réponses > le corps du texte
snprintf
Cette fonction nécessite une longueur spécifiée et le compilateur effectuera une vérification hors limites, il faut donc s'assurer que la longueur cible est plus longue que la somme de tous les paramètres. Mais considérez les procédures suivantes :
#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;
}
Après avoir ouvert ce programme-Wall
, une erreur sera signalée :
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
Cette erreur est attendue car il est effectivement possible de franchir la ligne. La question est donc : comment puis-je remplir la même fonction sans signaler d’erreur ?
Mongcc
版本比较新,7.1.1
, on estime que les anciennes versions du compilateur ne signaleront pas cette erreur.
PHP中文网2017-05-27 17:46:46
Tout d'abord, le deuxième paramètre de snprintf()
représente la taille du tampon, qui devrait ici être LENGTH
, sizeof(LENGTH)< / La valeur de code> est 4
(je suppose que ce que vous voulez écrire devrait être sizeof(cache)
). Alors, est-ce que tout ira bien après l'avoir changé en snprintf(cache, LENGTH, "%s/ruaruarua", cache);
? Jetons un coup d'œil à cet exemple : snprintf()
的第二个参数代表的是缓冲区的大小,在这里应该是LENGTH
,sizeof(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 callingsprintf()
,snprintf()
,vsprintf()
, andvsnprintf()
. Depending on the version ofgcc(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()
#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;
}
Cet exemple tente d'ajouter une chaîne à la fin de buf
, regardez le résultat
hello world
hello again
n'a pas obtenu les résultats escomptés. Pourquoi est-ce ? Il y a ce paragraphe dans le manuel de snprintf()
: #🎜🎜#
buf
Cependant, les standards notent explicitement que les résultats ne sont pas définis si les tampons source et de destination se chevauchent lors de l'appel de sprintf()
, . snprintf()
, vsprintf()
et vsnprintf()
Selon la version de gcc(1)
utilisée, et les options du compilateur utilisées, les appels tels que celui ci-dessus ne produiront pas les résultats attendus.#🎜🎜#
#🎜🎜#C'est-à-dire que si les tampons d'origine et de destination se chevauchent, les résultats d'exécution de ces fonctions de la famille printf()
ne seront pas définis. #🎜🎜#
#🎜🎜#Alors, comment « imprimer votre contenu original et du nouveau contenu dans un tableau » ? Une solution consiste à définir le tampon passé à snprintf()
à la fin de la chaîne dans le tableau : #🎜🎜#
rrreee
#🎜🎜#Alors comment ajouter continuellement des données à la fin du buffer ? Notez que la valeur de retour de la fonction de la famille printf()
est le nombre de caractères imprimés (nombre de caractères imprimés), alors vous pouvez l'appeler comme ceci : #🎜🎜#
rrreee
#🎜🎜#Le résultat est #🎜🎜#
rrreee