Niềng răng vuông []
dễ gõ hơn, kể từ khi thiết bị đầu cuối IBM 2741 được sử dụng rộng rãi trên hệ điều hành Multics " , đến lượt nó có Dennis Ritchie, một trong những người tạo ngôn ngữ C với tư cách là thành viên nhóm phát triển .
Lưu ý sự vắng mặt của dấu ngoặc nhọn ở bố cục IBM 2741!
Trong C, dấu ngoặc vuông được "lấy" vì chúng được sử dụng cho mảng và con trỏ . Nếu các nhà thiết kế ngôn ngữ mong đợi các mảng và con trỏ quan trọng hơn / được sử dụng thường xuyên hơn các khối mã (nghe có vẻ như một giả định hợp lý ở bên cạnh họ, nhiều hơn về bối cảnh lịch sử của phong cách mã hóa bên dưới), điều đó có nghĩa là các dấu ngoặc nhọn sẽ "ít quan trọng hơn" "Cú pháp.
Tầm quan trọng của mảng là khá rõ ràng trong bài viết Sự phát triển của ngôn ngữ C của Ritchie. Thậm chí còn có một giả định được tuyên bố rõ ràng về "sự phổ biến của con trỏ trong các chương trình C" .
... ngôn ngữ mới giữ lại một lời giải thích mạch lạc và khả thi (nếu không bình thường) về ngữ nghĩa của mảng ... Hai ý tưởng là đặc trưng nhất của C giữa các ngôn ngữ của lớp: mối quan hệ giữa mảng và con trỏ ... Đặc điểm khác của C, điều trị mảng của nó ... có những đức tính thực sự . Mặc dù mối quan hệ giữa con trỏ và mảng là không bình thường, nó có thể được học. Hơn nữa, ngôn ngữ cho thấy sức mạnh đáng kể để mô tả các khái niệm quan trọng, ví dụ, các vectơ có chiều dài thay đổi theo thời gian chạy, chỉ với một vài quy tắc và quy ước cơ bản ...
Để hiểu rõ hơn về bối cảnh lịch sử và phong cách mã hóa của thời điểm khi ngôn ngữ C được tạo ra, người ta cần phải tính đến việc "nguồn gốc của C gắn liền với sự phát triển của Unix" và cụ thể là chuyển hệ điều hành sang PDP- 11 "dẫn đến sự phát triển của phiên bản đầu của C" ( nguồn trích dẫn ). Theo Wikipedia , "vào năm 1972, Unix đã được viết lại bằng ngôn ngữ lập trình C" .
Mã nguồn của các phiên bản cũ khác nhau của Unix có sẵn trực tuyến, ví dụ như tại trang web Unix Tree . Trong số các phiên bản khác nhau được trình bày ở đó, hầu hết có liên quan dường như là Phiên bản thứ hai Unix ngày 1972-06:
Phiên bản thứ hai của Unix được phát triển cho PDP-11 tại Bell Labs bởi Ken Thompson, Dennis Ritchie và những người khác. Nó mở rộng Phiên bản đầu tiên với nhiều cuộc gọi hệ thống hơn và nhiều lệnh hơn. Phiên bản này cũng chứng kiến sự khởi đầu của ngôn ngữ C, được sử dụng để viết một số lệnh ...
Bạn có thể duyệt và nghiên cứu mã nguồn C từ trang Unix (V2) phiên bản thứ hai để có ý tưởng về phong cách mã hóa điển hình của thời đại.
Một ví dụ nổi bật hỗ trợ cho ý tưởng hồi đó khá quan trọng đối với lập trình viên để có thể nhập dấu ngoặc vuông dễ dàng có thể được tìm thấy trong mã nguồn 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;
Thật thú vị khi lưu ý cách động lực thực tế của việc chọn các ký tự để biểu thị các yếu tố cú pháp ngôn ngữ dựa trên việc sử dụng chúng trong các ứng dụng thực tế được nhắm mục tiêu giống như Luật của Zipf như được giải thích trong câu trả lời tuyệt vời này ...
mối quan hệ được quan sát giữa tần suất và độ dài được gọi là Luật của Zipf
... với sự khác biệt duy nhất là độ dài trong câu lệnh trên được thay thế bằng / khái quát là tốc độ gõ.