Y a-t-il une raison pour laquelle un nom de tableau n’est pas une lvalue?

Par exemple,

int x[10]; int i = 0; x = &i; //error occurs! 

Selon le Manuel de référence C-A , un nom de tableau ne peut pas être une valeur. Ainsi, x ne peut pas être une valeur. Mais, quelle est la raison pour laquelle le nom du tableau ne peut pas être une lvalue? Par exemple, pourquoi une erreur se produit-elle dans la troisième ligne?

Votre référence est incorrecte. Un tableau peut être une lvalue (mais pas une lvalue modifiable ), et un “nom de tableau” (identifiant) est toujours une lvalue.

Prenez votre exemple:

 int x[10]; int i = 0; x = &i; //error occurs! 

Appliquer le paragraphe C11 6.5.1, paragraphe 2:

Un identifiant est une expression primaire, à condition qu’il ait été déclaré comme désignant un object (auquel cas c’est une lvalue) …

Nous voyons que x est une expression primaire et une lvalue, car elle a déjà été déclarée comme désignant un object tableau.

Cependant, les règles du langage C stipulent qu’une expression de tableau dans divers contextes, y compris le côté gauche d’une expression d’affectation, est convertie en un pointeur pointant sur le premier élément du tableau et n’est pas une valeur lvalue, même si tableau était. Plus précisément:

Sauf s’il s’agit de l’opérande de l’opérateur sizeof, de l’opérateur _Alignof ou de l’opérateur unaire &, ou d’un littéral de chaîne utilisé pour initialiser un tableau, une expression de type ” tableau de type ” est convertie en expression avec type ” pointeur sur type ” qui pointe sur l’élément initial de l’object tableau et n’est pas une valeur lvalue. Si l’object tableau a une classe de stockage de registre, le comportement n’est pas défini.

(C11 6.3.2.1 paragraphe 3).

Le pointeur qui résulte de la conversion spécifiée ci-dessus n’est pas une valeur car une valeur désigne un object et il n’y a pas d’object approprié contenant la valeur du pointeur. l’object tableau contient les éléments du tableau et non un pointeur sur ces éléments.

L’exemple que vous utilisez dans votre question implique que vous compreniez qu’une expression de tableau se décompose (est convertie en) une valeur de pointeur, mais je pense que vous ne reconnaissez pas qu’après la conversion, la valeur du pointeur et le tableau sont deux choses différentes. Le pointeur n’est pas une valeur; le tableau pourrait être (et dans votre exemple, il est). Que les tableaux soient ou non des valeurs n’a en fait aucune incidence sur votre exemple; c’est la valeur du pointeur que vous essayez d’atsortingbuer.

Si vous deviez plutôt demander: Pourquoi les tableaux se décomposent-ils en indicateurs lorsqu’ils se trouvent à gauche d’un opérateur d’affectation? – alors je soupçonne qu’il n’y a pas de réponse particulièrement bonne. C ne permet tout simplement pas d’atsortingbution à des tableaux, historiquement.

Les noms de tableaux sont des valeurs non modifiables dans C. 🙂

Les tableaux sont nommés des étendues de mémoire où leurs éléments sont placés. Vous ne pouvez donc pas substituer une étendue de mémoire à une autre. Chaque extension de mémoire allouée initialement pour une déclaration de tableau a son propre nom unique. Chaque nom de tableau est lié à sa propre étendue de mémoire.

Il est vrai que les noms de tableaux génèrent des valeurs de pointeur dans de nombreux contextes. Mais l’opérateur & , et vous ne vous attendez pas à ce qu’il soit assignable.

 int i = 42; int *j = malloc(sizeof *j); &i = j; /* obviously wrong */ int a[] = {1,2,3}; &a[0] = j; /* also obviously wrong */ a = j; /* same as the previous line! */ 

Ainsi, lorsque vous étudiez la relation entre les tableaux et les pointeurs, rappelez-vous que a est généralement identique à &a[0] et vous ne penserez pas alors que lvalue-ness est une exception à la règle – il la suit parfaitement.

Un tableau est une valeur, mais il s’agit d’une valeur non modifiable.

C’est probablement lié à la compatibilité des types. Par exemple, vous pouvez faire ceci:

 struct ss { char c[10]; }; ... struct ss s1 = { { "hello" } }; struct ss s2 = s1; 

Mais pas ça:

 char s1[10] = "hello"; char s2[10] = s1;