Pourquoi est-ce que C de format de printf ont à la fois %c et %s?
Pourquoi est-ce que C de format de printf ont à la fois %c
et %s
?
Je sais que %c
représente un caractère unique et %s
représente un nul chaîne de caractères, mais ne serait pas la représentation de chaîne suffit?
- Probablement à distinguer entre une valeur null string et d'un caractère. Si ils ont juste eu
%s
, puis chaque personnage doit être null. char c = 'a';, dans ce casc
doit être null. C'est mon hypothèse bien 🙂 - Pourquoi ne pas mettre ça comme réponse, Surtout quand C'est de la réponse
- Hein? Que faire si vous voulez juste mettre un seul personnage, pourquoi devriez-vous besoin d'ajouter un NUL à elle? Ou n'ai-je pas obtenir quelque chose dans cette question?
- votre hypothèse est la réponse à cette question je crois
- Ouais, j'aurais upvoted comme une réponse comme je l'ai fait le commentaire haha.
- Là vous allez 🙂
%c
s'attend à un système de référence géodésique dechar
de type a de la valeur primitive.%s
s'attend à un système de référence géodésique dechar *
type, un pointeur. La différence entre eux est énorme en C, en dépit du fait qu'ils s'appliquer à du texte.
Vous devez vous connecter pour publier un commentaire.
Probablement de distinguer entre une valeur null string et d'un caractère. Si ils ont juste eu
%s
, puis chaque personnage doit être null.Dans le cas ci-dessus,
c
doit être null. C'est mon hypothèse bien 🙂%.1s
char
à l'intérieur d'un objet adressable, oui.%s
doit être null. Si il n'y a pas de%c
dans la langue, puis dans mon exemple ci-dessus, l'identificateur dec
doit être null pour être en mesure d'utiliser avec le spécificateur de format%s
.printf("%s", c)
ne serait pas le travail n'est pas parce que des non-résiliation, mais parce queprintf
attend%s
pour pointer vers un emplacement de la mémoire, tandis quec
est un personnage de la valeur. Null-résiliation est la raisonprintf("%s", &c)
ne fonctionnerait pas, mais même si il l'a fait, d'avoir un%c
identifiant toujours sens, car nécessitant&c
est incompatible avec la façon dont chaque variable, le type est imprimé. Donc, juste en disant: "c'est à cause de terminaison null" est incorrect.char*
à même d'obtenir un caractère à imprimer avec%s
. Juste rappelant ce qu'BlueRaja ditc
être unchar
, maisc
sera dans la plupart des cas être un int, et%c
fonctionne pourchar
etint
(à cause de la promotion du type).%s
imprime les caractères jusqu'à ce qu'il atteigne une0
(ou'\0'
, même chose).Si vous avez juste un
char x;
, l'impression avecprintf("%s", &x);
- vous devez fournir l'adresse, depuis%s
s'attend à unchar*
- donnerait des résultats inattendus, comme&x + 1
pourrait ne pas être0
.Donc on ne pouvait pas, il suffit d'imprimer un caractère unique, à moins que c'était nul (très inefficent).
EDIT: Comme d'autres l'ont souligné, les deux s'attendre à des choses différentes dans le var args paramètres - un pointeur, l'autre un seul char. Mais cette différence est assez clair.
%s
prend un pointeur alors que%c
prend un personnage lui-même.La question qui est mentionné par d'autres, qu'un personnage unique devrait être une valeur null n'est pas un vrai. Ce pourrait être traitée en fournissant une précision au format
%.1s
ferait l'affaire.Ce qui est plus important, à mon avis, c'est que pour
%s
sous toutes ses formes, vous auriez à fournir un pointeur vers un ou plusieurs caractères. Cela voudrait dire que vous ne serait pas en mesure d'imprimer des rvalues (expressions calculées, la fonction retourne etc) ou enregistrer des variables.Edit: je suis vraiment énervé par la réaction à cette réponse, je vais donc sans doute supprimer cela, ce n'est vraiment pas la peine. Il semble que les gens réagissent sur ce sans même avoir lu la question, ou de savoir comment apprécier la technicité de la question.
Que ce soit clair: je ne dis pas que vous devriez préférer
%.1s
sur%c
. Je dis seulement que les raisons pour lesquelles%c
ne peut pas être remplacé par différentes de la réponse à faire semblant de le dire. Ces autres réponses sont juste techniquement faux. Nulle la résiliation n'est pas un problème avec%s
.%.1s
sur%c
? Ce que vous faites est de ré-inventer un marqueur deprintf
...%.1s
aurait la fonctionnalité d'impression seulement un caractère qu'il ne faut pas même être une valeur null, alors la terminaison null n'est pas une objection valable à "introduire"%c
.%.1s
sur%c
? Parce qu'il n'est pas d'en ajouter un descripteur de format supplémentaire. À l'aide de précision dans le format descripteur est une fonctionnalité qui doit être assurée indépendamment de savoir si vous en avez besoin pour un seul caractère. Donc finalement, que serait vous faire économiser un supplément de spécification de format.%.1s
s'attendre à unchar
ou unchar*
?char x;
à la fonction. Donc il n'y a pas de réel avantage à l'utilisation de%.1s
sur%c
, parce que grâce à%.2s
nécessiterait un autre type de paramètre.printf("%c", 'a' + 8)
- vous ne pouvez pas écrire que `printf("%.1s", 'a' + 8)`%.1s
pour l'impression d'un personnage. Ce n'était pas la question. La question était de savoir si%c
qui était strictement nécessaire. Et je donne une réponse affirmative à qui, tout en indiquant que les raisons sont différentes que celles figurant dans les autres réponses.char
est un mot-clé. 😉rvalue
chose est une grosse affaire, mais qui ne peut être apprécié avec de l'expérience.De la fonction printf est une variadic fonction, ce qui signifie qu'il a nombre variable d'arguments. Les Arguments sont poussés sur la pile avant de la fonction (printf) est appelée. Pour que la fonction printf l'utilisation de la pile, il a besoin de connaître des informations sur ce qui est dans la pile, la chaîne de format est utilisé à cette fin.
par exemple
alors que
il n'est pas possible à l'intérieur de la fonction printf pour déterminer le contenu de pile par exemple, la distinction entre les " ch " et " s " parce que dans C il n'y a pas de vérification de type en cours d'exécution.
sizeof
cahier des charges. Tout d'abord,ch
est promue à unint
(ou sur certaines plates-formes pour uneunsigned
) etprintf
interprète quiint
comme un personnage. De sorte que la taille de ce paramètre sur la pile" estsizeof(int)
. Pour la seconde, vous vous trompez encore une fois, il estsizeof(char*)
et rien d'autre.sizeof(int)
peut (et de nos jours est souvent différent. Troisièmement, il n'est pas nécessaire que quelque chose comme une "pile" impliqués. Comment ces paramètres sont transmis à la discrétion de la plate-forme de l'ABI , et tout ce qui peut bien se passer dans les registres.%s
dit d'imprimer tous les caractères jusqu'à ce que vous trouver un nul (traiter la variable comme un pointeur).%c
dit imprimer un seul caractère (traiter la variable comme un code de caractère)À l'aide de
%s
pour un personnage qui ne fonctionne pas parce que le personnage va être traité comme un pointeur, alors il va essayer d'imprimer tous les caractères suivant que la place en mémoire jusqu'à ce qu'il trouve un nullDe voler les autres réponses de l'expliquer d'une manière différente.
Si vous voulez imprimer un caractère à l'aide
%s
, vous pouvez utiliser les éléments suivants pour bien passer l'adresse d'un char et de le garder à partir de l'écriture des ordures sur l'écran jusqu'à trouver une valeur null.'\0'
et pointeur null sont à la fois représentés en interne comme0
🙂0
. Leurs représentations internes peuvent être très différents; un caractère nul est généralement de 8 bits, tandis que un pointeur null est généralement 32 ou 64 bits. En outre, un pointeur null dans la représentation interne est pas forcément tous les bits à zéro (même si très souvent).if (pointer)
ouif (pointer != 0 )
ouif(pointer != NULL )
Aussi, je pense que 0s à l'aide de 8, 16, 32 bits ne sont pas très différents. bytes.com/topic/c/answers/213647-null-c0
, il existe dans le code source; employé dans un pointeur de contexte, le compilateur va la traduire de ce que la représentation interne est utilisé pour un pointeur null. Voir également la section 5 de la comp.lang.c FAQ. Il est vrai que plus implémentations utilisent tous les bits à zéro, mais il n'est pas nécessaire.Pour
%s
, nous avons besoin de fournir l'adresse de la chaîne, et non sa valeur.Pour
%c
, nous fournir la valeur de caractères.Si nous avons utilisé la
%s
au lieu de%c
, comment aurions-nous fournir un'\0'
après les personnages?Id tiens à ajouter un autre point de la perspective pour ce plaisir question.
Vraiment ce qui revient à le typage des données. J'ai vu des réponses sur ici que l'état que vous pourriez fournir un pointeur de type char, et de fournir un
Cela pourrait être vrai. Mais la réponse se trouve dans le C du concepteur d'essayer de donner plus de souplesse pour le programmeur, et en effet (quoique modeste) de la diminution de l'empreinte de votre application.
Parfois, un programmeur peut exécuter une série de if-else ou un switch-case, d'où le besoin de faire est de simplement la sortie d'un personnage basé sur l'état. Pour cela, dur le codage de caractères pourrait en effet prendre moins de place en mémoire que le seul caractères de 8 bits contre le pointeur qui est de 32 ou 64 bits (64 bits des ordinateurs). Un pointeur prendra plus d'espace dans la mémoire.
Si vous voulez réduire la taille grâce à l'utilisation réelle des chars contre des pointeurs de caractères, alors il ya deux façons, on pourrait penser à le faire dans les printf types d'opérateurs. On serait à la clé de l' .1s, mais comment est la routine supposé savoir, pour certains que vous êtes réellement fournir un type char contre un pointeur vers un char ou un pointeur vers une chaîne de caractères (tableau de caractères)? C'est pourquoi ils sont allés avec le "%c", car il est différent.
Plaisir Question 🙂
C a la
%c
et%s
les spécificateurs de format, car ils gèrent les différents types.Un
char
et une chaîne de caractères aussi différents que la nuit et 1.scanf(%s, &ch)
etscanf(%c, &ch)
états renvoie le même résultat.Envisager ch est un char commechar ch
;%c s'attend à un char, qui est un entier valeur et l'imprime selon les règles de codage.
%s s'attend à une pointeur à un emplacement de la mémoire qui contient char valeurs, et imprime les caractères de la localisation selon les règles d'encodage jusqu'à ce qu'il trouve un 0 (null) caractère.
Donc, vous voyez, sous le capot, les deux cas, alors qu'ils se ressemblent, ils n'ont pas beaucoup en commun, comme l'on travaille avec des valeurs et de l'autre avec des pointeurs. On est des instructions pour l'interprétation d'une valeur entière spécifique comme un ascii char, et l'autre est une itération le contenu d'un emplacement mémoire char par char et de l'interprétation jusqu'à une valeur de zéro est rencontré.
J'ai fait une expérience avec
printf("%.1s", &c)
etprintf("%c", c)
.J'ai utilisé le code ci-dessous pour tester, et le bash de
time
utilitaire d'obtenir le runing temps.Le résultat indique que l'utilisation de
%c
est 10 fois plus rapide que%.1s
. Ainsi, bien qu ' %s pouvez faire le travail de %c %c est encore nécessaire pour la performance.Depuis, personne n'a fourni de réponse avec QUELQUE manière que ce soit, ici, c'est un printf spécification de pubs.opengroup.com qui est similaire à la définition d'un format de IBM