Dans le premier cas, la non-littéral de chaîne de format pourrait peut-être venir de code d'utilisateur ou fourni par l'utilisateur (run-time) de données, auquel cas elle peut contenir %s
ou à d'autres spécifications de conversion, pour lequel vous n'avez pas transmis les données. Cela peut conduire à toutes sortes de problèmes de lecture (et d'écriture des problèmes si la chaîne contient %n
- voir printf()
ou votre bibliothèque C les pages de manuel).
Dans le second cas, le format de la chaîne de contrôle à la sortie et il n'a pas d'importance si une chaîne de caractères à imprimer contient des spécifications de conversion ou pas (bien que le code indiqué imprime un entier, pas une chaîne de caractères). Le compilateur (GCC ou Clang est utilisé dans la question) suppose que parce qu'il y a des arguments après le (non-littérale) chaîne de format, le programmeur sait ce qu'ils font.
La première est une " chaîne de format de la vulnérabilité. Vous pouvez effectuer une recherche pour plus d'informations sur le sujet.
GCC sait que la plupart du temps le seul argument printf()
, avec une non-littéral de chaîne de format est une invitation à la difficulté. Vous pouvez utiliser puts()
ou fputs()
à la place. Il est suffisamment dangereux que GCC génère des avertissements avec le minimum de provocation.
Le problème plus général de non-littéral de chaîne de format peut aussi être problématique si vous n'êtes pas prudent - mais extrêmement utile en supposant que vous êtes prudent. Vous devez travailler dur pour obtenir de GCC à se plaindre: il faut à la fois -Wformat
et -Wformat-nonliteral
pour obtenir la plainte.
À partir des commentaires:
Donc, en ignorant l'avertissement, comme si je sais vraiment ce que je fais et il n'y aura pas d'erreurs, est l'un ou l'autre est plus efficace d'utiliser ou sont-ils les mêmes? En considérant à la fois l'espace et le temps.
De vos trois printf()
des déclarations, étant donné les contraintes de contexte que la variable s
est attribué immédiatement au-dessus de l'appel, il n'y a pas de problème réel. Mais vous pouvez utiliser puts(s)
si vous avez omis le retour à la ligne à partir de la chaîne ou de l' fputs(s, stdout)
comme il est et obtenir le même résultat, sans la surcharge d' printf()
analyse de l'ensemble de la chaîne de constater qu'il est tout simple de caractères à imprimer.
Le deuxième printf()
déclaration est également sans danger comme l'écrit; la chaîne de format correspond aux données transmises. Il n'y a pas de différence significative entre cela et un simple passage de la chaîne de format comme un littéral - sauf que le compilateur peut faire plus de vérifier si la chaîne de format est un littéral. Le résultat est le même.
Le tiers - printf()
passe plus de données arguments que le format de la chaîne de besoins, mais c'est bénin. Ce n'est pas l'idéal, si. Encore une fois, le compilateur peut vérifier mieux si la chaîne de format est un littéral, mais la durée d'effet est pratiquement la même.
De la printf()
spécification liée au dessus:
Chacune de ces fonctions, des convertis, des formats, et imprime ses arguments sous le contrôle du format. Le format est une chaîne de caractères, en commençant et se terminant dans son état de décalage initial, le cas échéant. Le format est composé de zéro, une ou plusieurs directives: les caractères ordinaires, qui sont simplement copiés sur le flux de sortie, et les spécifications de conversion, qui doit aboutir à la récupération de zéro ou plusieurs arguments. Les résultats ne sont pas définis si il n'existe pas suffisamment d'arguments pour le format. Si le format est épuisé alors que les arguments restent, l'excès d'arguments doit être évalué, mais ne sont pas ignorés.
Dans tous ces cas, il n'y a aucune indication de la chaîne de format n'est pas littérale. Cependant, une des raisons de vouloir un non-littéral de chaîne de format peut-être que, parfois, vous imprimez des nombres en virgule flottante en %f
notation et, parfois, en %e
de la notation, et vous devez choisir au moment de l'exécution. (Si c'est simplement basée sur la valeur, %g
pourrait être approprié, mais il ya des moments où vous souhaitez que le contrôle explicite - toujours %e
ou toujours %f
.)