101 votes

Pourquoi C autorise pas concaténer des chaînes lorsque vous utilisez l’opérateur ternaire ?

Le code suivant compile sans problème :

Toutefois, cela ne compile pas :

Quelle est la raison pour cela ?

137voto

Sourav Ghosh Points 54713

Conformément à la norme C11, chapitre §5.1.1.2, de concaténation de chaîne adjacents littéraux:

Adjacent littéral de chaîne de tokens sont concaténées.

arrive dans la phase de traduction. Sur l'autre main:

printf("Hi" (test ? "Bye" : "Goodbye"));

implique l'opérateur conditionnel, qui est évaluée au moment de l'exécution. Ainsi, au moment de la compilation, au cours de la phase de traduction, il n'y a pas adjacent littéraux de chaîne actuelle, d'où la concaténation n'est pas possible. La syntaxe n'est pas valide et donc rapporté par votre compilateur.


Pour élaborer un peu sur le pourquoi de la partie, au cours de la phase de prétraitement, de la côté des littéraux de chaîne sont concaténés et représenté comme un seul littéral de chaîne (token). Le stockage est alloué en conséquence et la concaténation de chaîne de caractères littérale est considéré comme une seule entité (un littéral de chaîne).

D'autre part, en cas d'exécution de concaténation, la destination doit avoir assez de mémoire pour contenir la concaténation de chaîne de caractères littérale sinon, il n'y aura aucun moyen de les attendre concaténées de sortie peut être consulté. Maintenant, dans le cas de littéraux de chaîne, ils sont déjà alloué de la mémoire au moment de la compilation et ne peut être prolongé pour tenir dans une plus entrants entrée en ou annexé à l'original du contenu. En d'autres termes, il n'y aura aucun moyen de faire la concaténation de résultat peut être consulté (présenté) comme une seule chaîne de caractères littérale. Ainsi, cette construction dans intrinsèquement erronée.

Juste pour info, pour le temps d'exécution de la chaîne (pas de littéraux) concaténation, nous avons une fonction de la bibliothèque strcat() qui concatène deux chaînes. Avis, la description mentionne:

char *strcat(char * restrict s1,const char * restrict s2);

L' strcat() fonction ajoute une copie de la chaîne pointée par s2 (y compris le caractère de fin null) à la fin de la chaîne pointée par s1. Le premier caractère d' s2 remplace le caractère nul à la fin de l' s1. [...]

Donc, on peut le voir, l' s1 est une chaîne de caractères, pas un littéral de chaîne. Cependant, comme le contenu de s2 n'est pas modifié en aucune façon, il peut très bien être une chaîne littérale.

123voto

Vlad from Moscow Points 36219

Selon la Norme (5.1.1.2 Traduction phases)

1 La préséance entre les règles de syntaxe de la traduction est fixée par les phases suivantes.6)

  1. Adjacent littéral de chaîne de tokens sont concaténées.

Et seulement après que

  1. Des espaces blancs séparant les jetons sont pas plus importante. Chaque prétraitement jeton est converti en un jeton. Le résultant les jetons sont syntaxiquement et sémantiquement analysées et traduites en tant que l'unité de traduction.

Dans cette construction

"Hi" (test ? "Bye" : "Goodbye")

il n'y a pas adjacent littéral de chaîne de jetons. Si cette construction n'est pas valide.

41voto

Un littéral de chaîne de concaténation est effectuée par le préprocesseur au moment de la compilation. Il n'existe aucun moyen pour cette concaténation d'être conscient de la valeur de test, ce qui n'est pas connue jusqu'à ce que le programme s'exécute en fait. Par conséquent, ces littéraux de chaîne ne peut pas être concaténés.

Parce que le cas général est que tu n'aurais pas une construction de ce genre pour des valeurs connues à la compilation, le C standard a été conçu pour limiter l'auto-concaténation de fonctionnalité à la plupart des base de cas: lorsque les littéraux sont littéralement juste à côté les uns des autres.

Mais même si elle n'a pas de mot cette restriction de cette façon, ou si la restriction ont été différemment construits, votre exemple serait toujours impossible à réaliser sans faire de la concaténation d'un processus d'exécution. Et, pour cela, nous avons la bibliothèque de fonctions telles que l' strcat.

31voto

Unsigned Points 3312

Parce que le C n'a pas d' string type. Les littéraux de chaîne sont compilées char tableaux, référencé par un char* pointeur.

C permet adjacentes littéraux être combiné au moment de la compilation, comme dans votre premier exemple. Le compilateur C lui-même a une certaine connaissance sur les chaînes. Mais cette information n'est pas présent au moment de l'exécution, et donc la concaténation ne peut pas se produire.

Pendant le processus de compilation, votre premier exemple est "traduit" à:

int main() {
    static const char char_ptr_1[] = {'H', 'i', 'B', 'y', 'e', '\0'};
    printf(char_ptr_1);
}

Notez comment les deux chaînes sont combinés en un seul tableau statique par le compilateur, avant que le programme ne jamais s'exécute.

Cependant, votre deuxième exemple est "traduit" à quelque chose comme ceci:

int main() {
    static const char char_ptr_1[] = {'H', 'i', '\0'};
    static const char char_ptr_2[] = {'B', 'y', 'e', '\0'};
    static const char char_ptr_3[] = {'G', 'o', 'o', 'd', 'b', 'y', 'e', '\0'};
    int test = 0;
    printf(char_ptr_1 (test ? char_ptr_2 : char_ptr_3));
}

Il devrait être clair pourquoi ce ne compile pas. L'opérateur ternaire ? est évaluée au moment de l'exécution, et non pas au moment de la compilation, lorsque les "cordes" n'existe plus en tant que tel, mais seulement en tant que simple char tableaux, référencé par char* des pointeurs. Contrairement à adjacentes littéraux de chaîne, à côté pointeurs de char sont tout simplement une erreur de syntaxe.

14voto

Eric Points 903

Si vous voulez vraiment avoir les deux branches à produire des constantes de chaîne de compilation à choisir lors de l’exécution, vous aurez besoin d’une macro.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X