Les accolades carrées []
sont plus faciles à taper depuis le terminal IBM 2741 "largement utilisé sur le système d’ exploitation Multics" , qui avait à son tour Dennis Ritchie, l’un des créateurs du langage C, en tant que membre de l’équipe de développement .
Notez l' absence d'accolades chez IBM 2741!
En C, les accolades carrées sont "prises" car elles sont utilisées pour les tableaux et les pointeurs . Si les concepteurs de langage s'attendaient à ce que les tableaux et les pointeurs soient plus importants / utilisés plus fréquemment que les blocs de code (ce qui semble être une hypothèse raisonnable à leurs côtés, plutôt que sur le contexte historique du style de codage ci-dessous), cela signifierait que les accolades seraient moins importantes. "syntaxe.
L’importance des tableaux est assez évidente dans l’article Le développement du langage C de Ritchie. Il existe même une hypothèse explicite de "prévalence de pointeurs dans les programmes C" .
... le nouveau langage a conservé une explication cohérente et exploitable (s’il est inhabituel) de la sémantique des tableaux ... Deux idées sont les plus caractéristiques du C parmi les langages de sa classe: la relation entre les tableaux et les pointeurs ... L’autre trait caractéristique de C, son traitement des tableaux ... a de véritables vertus . Bien que la relation entre les pointeurs et les tableaux soit inhabituelle, vous pouvez l'apprendre. De plus, le langage montre un pouvoir considérable pour décrire des concepts importants, par exemple des vecteurs dont la longueur varie au moment de l'exécution, avec seulement quelques règles et conventions de base ...
Pour mieux comprendre le contexte historique et le style de codage de l'époque de la création du langage C, il convient de prendre en compte le fait que "l'origine de C est étroitement liée au développement de l'Unix" et, en particulier, que le transfert du système d'exploitation vers un PDP- 11 "ont conduit au développement d’une première version de C" ( source de citations ). Selon Wikipedia , "en 1972, Unix a été réécrit dans le langage de programmation C" .
Le code source de diverses anciennes versions d'Unix est disponible en ligne, par exemple sur le site de l' arbre Unix . Parmi les différentes versions présentées, la plus pertinente semble être la deuxième édition Unix de 1972-06:
La deuxième édition d'Unix a été développée pour le PDP-11 chez Bell Labs par Ken Thompson, Dennis Ritchie et d'autres. Il a étendu la première édition avec plus d'appels système et plus de commandes. Cette édition a également vu le début du langage C, qui était utilisé pour écrire certaines des commandes ...
Vous pouvez parcourir et étudier le code source en C depuis la page Second Edition Unix (V2) pour avoir une idée du style de codage typique de l'époque.
Un exemple frappant qui soutient l'idée qu'il était alors très important pour le programmeur de pouvoir taper facilement des crochets se trouve dans le code source V2 / c / ncc.c :
/* C command */
main(argc, argv)
char argv[][]; {
extern callsys, printf, unlink, link, nodup;
extern getsuf, setsuf, copy;
extern tsp;
extern tmp0, tmp1, tmp2, tmp3;
char tmp0[], tmp1[], tmp2[], tmp3[];
char glotch[100][], clist[50][], llist[50][], ts[500];
char tsp[], av[50][], t[];
auto nc, nl, cflag, i, j, c;
tmp0 = tmp1 = tmp2 = tmp3 = "//";
tsp = ts;
i = nc = nl = cflag = 0;
while(++i < argc) {
if(*argv[i] == '-' & argv[i][1]=='c')
cflag++;
else {
t = copy(argv[i]);
if((c=getsuf(t))=='c') {
clist[nc++] = t;
llist[nl++] = setsuf(copy(t));
} else {
if (nodup(llist, t))
llist[nl++] = t;
}
}
}
if(nc==0)
goto nocom;
tmp0 = copy("/tmp/ctm0a");
while((c=open(tmp0, 0))>=0) {
close(c);
tmp0[9]++;
}
while((creat(tmp0, 012))<0)
tmp0[9]++;
intr(delfil);
(tmp1 = copy(tmp0))[8] = '1';
(tmp2 = copy(tmp0))[8] = '2';
(tmp3 = copy(tmp0))[8] = '3';
i = 0;
while(i<nc) {
if (nc>1)
printf("%s:\n", clist[i]);
av[0] = "c0";
av[1] = clist[i];
av[2] = tmp1;
av[3] = tmp2;
av[4] = 0;
if (callsys("/usr/lib/c0", av)) {
cflag++;
goto loop;
}
av[0] = "c1";
av[1] = tmp1;
av[2] = tmp2;
av[3] = tmp3;
av[4] = 0;
if(callsys("/usr/lib/c1", av)) {
cflag++;
goto loop;
}
av[0] = "as";
av[1] = "-";
av[2] = tmp3;
av[3] = 0;
callsys("/bin/as", av);
t = setsuf(clist[i]);
unlink(t);
if(link("a.out", t) | unlink("a.out")) {
printf("move failed: %s\n", t);
cflag++;
}
loop:;
i++;
}
nocom:
if (cflag==0 & nl!=0) {
i = 0;
av[0] = "ld";
av[1] = "/usr/lib/crt0.o";
j = 2;
while(i<nl)
av[j++] = llist[i++];
av[j++] = "-lc";
av[j++] = "-l";
av[j++] = 0;
callsys("/bin/ld", av);
}
delfil:
dexit();
}
dexit()
{
extern tmp0, tmp1, tmp2, tmp3;
unlink(tmp1);
unlink(tmp2);
unlink(tmp3);
unlink(tmp0);
exit();
}
getsuf(s)
char s[];
{
extern exit, printf;
auto c;
char t, os[];
c = 0;
os = s;
while(t = *s++)
if (t=='/')
c = 0;
else
c++;
s =- 3;
if (c<=8 & c>2 & *s++=='.' & *s=='c')
return('c');
return(0);
}
setsuf(s)
char s[];
{
char os[];
os = s;
while(*s++);
s[-2] = 'o';
return(os);
}
callsys(f, v)
char f[], v[][]; {
extern fork, execv, wait, printf;
auto t, status;
if ((t=fork())==0) {
execv(f, v);
printf("Can't find %s\n", f);
exit(1);
} else
if (t == -1) {
printf("Try again\n");
return(1);
}
while(t!=wait(&status));
if ((t=(status&0377)) != 0) {
if (t!=9) /* interrupt */
printf("Fatal error in %s\n", f);
dexit();
}
return((status>>8) & 0377);
}
copy(s)
char s[]; {
extern tsp;
char tsp[], otsp[];
otsp = tsp;
while(*tsp++ = *s++);
return(otsp);
}
nodup(l, s)
char l[][], s[]; {
char t[], os[], c;
os = s;
while(t = *l++) {
s = os;
while(c = *s++)
if (c != *t++) goto ll;
if (*t++ == '\0') return (0);
ll:;
}
return(1);
}
tsp;
tmp0;
tmp1;
tmp2;
tmp3;
Il est intéressant de noter comment la motivation pragmatique de la sélection de caractères pour désigner des éléments de syntaxe de langage basés sur leur utilisation dans des applications pratiques ciblées ressemble à la loi de Zipf, comme expliqué dans cette réponse géniale ...
la relation observée entre la fréquence et la longueur est appelée loi de Zipf
... à la seule différence que la longueur indiquée ci-dessus est remplacée par / généralisée par la vitesse de frappe.