Voici mon point de vue:
Le développement du langage C offre un aperçu de l'évolution du type de tableau en C:
Je vais essayer de décrire le tableau:
Les précurseurs B et BCPL de C n'avaient pas de type de tableau distinct, une déclaration comme:
auto V[10] (B)
or
let V = vec 10 (BCPL)
déclarerait V comme étant un pointeur (non typé) qui est initialisé pour pointer vers une région inutilisée de 10 "mots" de mémoire. B déjà utilisé *
pour pointer déréférencement et a la []
notation de sténographie, *(V+i)
signifiait V[i]
, comme dans aujourd'hui C / C. Cependant, ce V
n'est pas un tableau, c'est toujours un pointeur qui doit pointer vers une certaine mémoire. Cela a causé des problèmes lorsque Dennis Ritchie a essayé d'étendre B avec des types de structure. Il voulait que les tableaux fassent partie des structures, comme en C aujourd'hui:
struct {
int inumber;
char name[14];
};
Mais avec le concept B, BCPL des tableaux en tant que pointeurs, cela aurait exigé que le name
champ contienne un pointeur qui devait être initialisé à l'exécution sur une région mémoire de 14 octets dans la structure. Le problème d'initialisation / mise en page a finalement été résolu en donnant aux tableaux un traitement spécial: le compilateur suivrait l'emplacement des tableaux dans les structures, sur la pile, etc. sans nécessiter réellement la matérialisation du pointeur vers les données, sauf dans les expressions qui impliquent les tableaux. Ce traitement permettait à presque tout le code B de continuer à s'exécuter et est la source de la règle «les tableaux convertis en pointeur si vous les regardez» . C'est un hack de compatibilité, qui s'est avéré très pratique, car il permettait des tableaux de taille ouverte, etc.
Et voici ma supposition pourquoi le tableau ne peut pas être attribué: Puisque les tableaux étaient des pointeurs en B, vous pouvez simplement écrire:
auto V[10];
V=V+5;
pour rebaser un "tableau". Cela n'avait plus de sens, car la base d'une variable de tableau n'était plus une lvalue. Donc, cette attribution a été interdite, ce qui a aidé à attraper les quelques programmes qui ont fait ce rebasage sur des tableaux déclarés. Et puis cette notion est restée: comme les tableaux n'ont jamais été conçus pour être des citations de première classe du système de type C, ils étaient principalement traités comme des bêtes spéciales qui deviennent des pointeurs si vous les utilisez. Et d'un certain point de vue (qui ignore que les C-arrays sont un hack bâclé), interdire l'affectation de tableaux a encore du sens: un tableau ouvert ou un paramètre de fonction de tableau est traité comme un pointeur sans informations de taille. Le compilateur ne dispose pas des informations pour générer une affectation de tableau pour eux et l'affectation de pointeur était requise pour des raisons de compatibilité.
typedef int vec[3];
void f(vec a, vec b)
{
vec x,y;
a=b;
x=y;
a=x;
x=a;
}
Cela n'a pas changé lorsqu'une révision de C en 1978 a ajouté l'affectation de structure ( http://cm.bell-labs.com/cm/cs/who/dmr/cchanges.pdf ). Même si les enregistrements étaient des types distincts en C, il n'était pas possible de les affecter au début de K&R C. Vous deviez les copier membre par membre avec memcpy et vous ne pouviez leur passer que des pointeurs comme paramètres de fonction. L'assignation (et le passage des paramètres) était maintenant simplement définie comme le memcpy de la mémoire brute de la structure et comme cela ne pouvait pas casser le code existant, il était facilement adopté. En tant qu'effet secondaire involontaire, cela introduisit implicitement une sorte d'assignation de tableau, mais cela se produisait quelque part dans une structure, donc cela ne pouvait pas vraiment poser de problèmes avec la façon dont les tableaux étaient utilisés.