เหตุใดภาษาการเขียนโปรแกรมโดยเฉพาะ C ใช้วงเล็บปีกกาและไม่ใช่รูปสี่เหลี่ยมจัตุรัส


96

คำจำกัดความของ "ภาษา C-Style" สามารถทำให้ง่ายลงได้ถึง "ใช้วงเล็บปีกกา ( {})" ทำไมเราถึงใช้ตัวละครนั้น (และทำไมบางอย่างไม่สมเหตุสมผลมากกว่าอย่างเช่น[]ซึ่งไม่ต้องการปุ่ม Shift อย่างน้อยในคีย์บอร์ดของสหรัฐอเมริกา)

มีประโยชน์จริงใด ๆ ต่อผลผลิตของโปรแกรมเมอร์ที่มาจากเครื่องหมายปีกกาหรือนักออกแบบภาษาใหม่ควรมองหาทางเลือกอื่น (เช่นคนที่อยู่เบื้องหลัง Python)

Wikipediaบอกเราว่า C ใช้เครื่องหมายปีกกาดังกล่าว แต่ไม่ใช่เพราะอะไร คำแถลงในบทความ Wikipedia ในรายการภาษาโปรแกรม C-basedแสดงให้เห็นว่าองค์ประกอบไวยากรณ์นี้ค่อนข้างพิเศษ:

ในวงกว้างการพูดภาษาตระกูล C เป็นภาษาที่ใช้ไวยากรณ์บล็อกแบบคล้าย C (รวมถึงเครื่องหมายปีกกาเพื่อเริ่มและจบบล็อก) ...


35
บุคคลเดียวที่สามารถตอบคำถามนี้ได้คือ Dennis Ritchie และเขาตายไปแล้ว การเดาที่สมเหตุสมผลคือ [] ถูกใช้ไปแล้วสำหรับอาร์เรย์
Dirk Holsopple

2
@ DirkHolsopple ดังนั้นเขาไม่ทิ้งเหตุผลไว้ข้างหลัง? DRAT อีกทั้งสอง downvote สำหรับสิ่งที่ฉันอยากรู้เกี่ยวกับ? ขอบคุณพวก ....
ลูกแมวบางคน

1
โปรดอภิปรายเกี่ยวกับคำถามนี้ในคำถาม Meta นี้ต่อ
Thomas Owens

2
ฉันได้ปลดล็อกโพสต์นี้แล้ว โปรดให้ความเห็นใด ๆ เกี่ยวกับคำถามและการอภิปรายเกี่ยวกับความเหมาะสมในคำถาม Meta
โธมัสโอเวนส์

5
มันอาจจะมีบางอย่างเกี่ยวข้องกับความจริงที่ว่ามีการใช้เครื่องหมายปีกกาในการจัดวางสัญลักษณ์ในคณิตศาสตร์ทำให้พวกเขาค่อนข้างงุ่มง่ามที่จะใช้สำหรับการเข้าถึงองค์ประกอบของอาร์เรย์ แม้แต่ภาษาสมัยใหม่เช่น Python ก็ใช้เครื่องหมายปีกกาเพื่อประกาศชุดและพจนานุกรม คำถามก็คือทำไม C ถึงใช้เครื่องหมายปีกกาเพื่อประกาศขอบเขตด้วย? อาจเป็นเพราะนักออกแบบไม่ชอบทางเลือกที่รู้จักเช่น BEGIN / END และสัญกรณ์การเข้าถึงอาร์เรย์ที่มากเกินไป ([]) ถือว่ามีความสวยงามน้อยกว่าการตั้งค่าสัญกรณ์
Charles Salvia

คำตอบ:


102

อิทธิพลที่สำคัญสองประการต่อ C คือตระกูลภาษา Algol (Algol 60 และ Algol 68) และ BCPL (ซึ่ง C ใช้ชื่อ)

BCPL เป็นภาษาโปรแกรมวงเล็บปีกกาแรกและวงเล็บปีกการอดชีวิตจากการเปลี่ยนแปลงทางไวยากรณ์และกลายเป็นวิธีการทั่วไปในการแสดงคำสั่งซอร์สโค้ดโปรแกรม ในทางปฏิบัติบนแป้นพิมพ์ที่ จำกัด ของวันโปรแกรมต้นฉบับมักใช้ลำดับ $ (และ $) แทนสัญลักษณ์ {และ} ความคิดเห็นบรรทัดเดียว '//' ของ BCPL ซึ่งไม่ได้นำมาใช้ใน C จะปรากฏขึ้นอีกครั้งใน C ++ และต่อมาใน C99

จากhttp://www.princeton.edu/~achaney/tmve/wiki100k/docs/BCPL.html

BCPL แนะนำและนำนวัตกรรมมาใช้หลายอย่างซึ่งกลายเป็นองค์ประกอบทั่วไปในการออกแบบภาษาต่อมา ดังนั้นจึงเป็นภาษาการเขียนโปรแกรมคร่อมตัวแรก (หนึ่งที่ใช้ {} เป็นตัวคั่นบล็อก) และมันเป็นภาษาแรกที่ใช้ // เพื่อทำเครื่องหมายความคิดเห็นแบบอินไลน์

จากhttp://progopedia.com/language/bcpl/

ภายใน BCPL เรามักจะเห็นเครื่องมือจัดฟันแบบโค้ง แต่ไม่เสมอไป นี่เป็นข้อ จำกัด ของแป้นพิมพ์ในเวลา ตัวละคร$(และ$)เป็น lexicographically เทียบเท่ากับและ { Digraphs และ trigraphsได้รับการบำรุงรักษาใน C (แม้ว่าจะเป็นชุดที่แตกต่างกันสำหรับการแทนที่รั้งหยิก - และ)}??<??>

การใช้วงเล็บปีกกาถูกขัดเกลาเพิ่มเติมในB (ซึ่งก่อนหน้านี้ C)

จากการอ้างอิงของผู้ใช้ถึง Bโดย Ken Thompson:

/* The following function will print a non-negative number, n, to
  the base b, where 2<=b<=10,  This routine uses the fact that
  in the ASCII character set, the digits 0 to 9 have sequential
  code values.  */

printn(n,b) {
        extern putchar;
        auto a;

        if(a=n/b) /* assignment, not test for equality */
                printn(a, b); /* recursive */
        putchar(n%b + '0');
}

มีข้อบ่งชี้ว่ามีการใช้เครื่องมือจัดฟันแบบหยิกเป็นมือสั้นbeginและendภายในอัลกอล

ฉันจำได้ว่าคุณรวมไว้ในรหัสการ์ด 256 ตัวอักษรที่คุณเผยแพร่ใน CACM เพราะฉันคิดว่ามันน่าสนใจที่คุณเสนอว่าพวกเขาสามารถใช้แทนคำหลัก 'เริ่มต้น' และ 'สิ้นสุด' ซึ่งก็คือ วิธีที่ใช้ในภาษา C ในภายหลัง

จากhttp://www.bobbemer.com/BRACES.HTM


การใช้วงเล็บเหลี่ยม (แทนคำแนะนำในคำถาม) กลับไปยิ่งขึ้น ดังที่กล่าวไว้ตระกูลอัลกอลมีอิทธิพลต่อซีภายในอัลกอล 60 และ 68 (ซีเขียนในปี 1972 และ BCPL ในปี 1966) วงเล็บสี่เหลี่ยมถูกใช้เพื่อกำหนดดัชนีให้เป็นอาร์เรย์หรือเมทริกซ์

BEGIN
  FILE F(KIND=REMOTE);
  EBCDIC ARRAY E[0:11];
  REPLACE E BY "HELLO WORLD!";
  WRITE(F, *, E);
END.

เนื่องจากโปรแกรมเมอร์คุ้นเคยกับวงเล็บเหลี่ยมสำหรับอาร์เรย์ใน Algol และ BCPL และวงเล็บปีกกาสำหรับบล็อกใน BCPL จึงมีความต้องการหรือความปรารถนาเล็กน้อยที่จะเปลี่ยนแปลงสิ่งนี้เมื่อสร้างภาษาอื่น


คำถามที่อัปเดตประกอบด้วยภาคผนวกของการเพิ่มประสิทธิภาพสำหรับการใช้งานปีกกาแบบหยักและ python ที่กล่าวถึง มีแหล่งข้อมูลอื่น ๆ ที่ทำการศึกษานี้แม้ว่าคำตอบจะเดือดร้อนถึง "ข้อมูลเล็ก ๆ น้อย ๆ และสิ่งที่คุณคุ้นเคยคือสิ่งที่คุณมีประสิทธิผลมากที่สุด" เนื่องจากทักษะที่แตกต่างกันอย่างกว้างขวางในการเขียนโปรแกรมและความคุ้นเคยกับภาษาที่แตกต่างกันเหล่านี้กลายเป็นเรื่องยากที่จะบัญชี

ดูเพิ่มเติม: Stack Overflow มีการศึกษาทางสถิติที่ระบุว่า Python มีประสิทธิภาพมากกว่าหรือไม่

กำไรส่วนใหญ่จะขึ้นอยู่กับ IDE (หรือขาด) ที่ใช้ ในโปรแกรมแก้ไขที่ใช้ vi การวางเคอร์เซอร์บนการจับคู่เปิด / ปิดแบบหนึ่งและการจับคู่%จะเลื่อนเคอร์เซอร์ไปที่อักขระที่ตรงกันอีกชุด นี่เป็นสิ่งที่มีประสิทธิภาพมากเมื่อใช้ภาษา C ในสมัยก่อน - น้อยลงแล้วในตอนนี้

การเปรียบเทียบที่ดีกว่าจะอยู่ระหว่าง{}และbegin/ endซึ่งเป็นตัวเลือกของวัน (พื้นที่แนวนอนนั้นมีค่า) ภาษาเวิร์ ธ หลายแห่งมีพื้นฐานมาจาก a beginและendstyle (Algol (ดังกล่าวข้างต้น), pascal (หลายคนคุ้นเคย) และตระกูล Modula

ฉันมีปัญหาในการค้นหาสิ่งใดที่แยกคุณลักษณะภาษาเฉพาะนี้ - ที่ดีที่สุดที่ฉันสามารถทำได้คือแสดงให้เห็นว่าภาษาวงเล็บปีกกาเป็นที่นิยมมากกว่าภาษาเริ่มต้นและเป็นโครงสร้างทั่วไป ดังที่ได้กล่าวไว้ในลิงก์ Bob Bemer ด้านบนวงเล็บปีกกาถูกใช้เพื่อทำให้การเขียนโปรแกรมง่ายขึ้นเมื่อจดชวเลข

จากเหตุผลที่ Pascal ไม่ใช่ภาษาโปรแกรมโปรดของฉัน

โปรแกรมเมอร์ C และ Ratfor พบว่า 'เริ่มต้น' และ 'สิ้นสุด' เทอะทะเมื่อเปรียบเทียบกับ {และ}

ซึ่งเป็นเรื่องเกี่ยวกับสิ่งที่สามารถพูดได้ - ความคุ้นเคยและความชอบ


14
ตอนนี้ทุกคนที่นี่กำลังเรียนรู้ BCPL แทนที่จะทำงาน :)
Denys Séguret

trigraphs (แนะนำในปี 1989 มาตรฐาน ISO C) สำหรับ{และ}มีและ??< ??>digraphs (แนะนำโดยการแก้ไข 1995) เป็นและ<% %>Trigraphs มีการขยายในทุกบริบทในช่วงการแปลเร็วมาก Digraphs เป็นโทเค็นและไม่ได้ขยายเป็นตัวอักษรสตริงค่าคงที่อักขระหรือความคิดเห็น
Keith Thompson

มีบางอย่างก่อนปี 1989 สำหรับเรื่องนี้ใน C (ฉันต้องขุดหนังสือฉบับพิมพ์ครั้งแรกของฉันเพื่อรับวันที่) หน้ารหัส EBCDIC ไม่ทั้งหมดมีวงเล็บปีกกา (หรือวงเล็บเหลี่ยม) อยู่ในพวกเขาและมีข้อกำหนดสำหรับสิ่งนี้ในคอมไพเลอร์ C แรกสุด

@NevilleDNZ BCPL ใช้เครื่องมือจัดฟันแบบโค้งในปี 1966 ที่ Algol68 ได้รับความคิดจากสิ่งที่จะสำรวจ - แต่ BCPL ไม่ได้รับจาก Algo68 ผู้ประกอบการที่สามเป็นสิ่งที่ฉันสนใจและติดตามกลับไปที่ CPL (1963) (ผู้บุกเบิกของ BCPL) ซึ่งยืมแนวคิดจาก Lisp (1958)

1968: Algol68 อนุญาตให้มีเครื่องหมายวงเล็บกลม (~) เป็นชวเลขของการเริ่มต้น ~ สิ้นสุด บล็อกสัญลักษณ์ตัวหนา เหล่านี้จะเรียกสั้น ๆสัญลักษณ์ CF WP: สัญลักษณ์ Algol68 หนานี้จะช่วยให้บล็อกของรหัสที่จะได้รับการปฏิบัติเช่นเดียวกับการแสดงออก A68 ยังมีสั้น ๆ shorthands เช่น C ของ: ประกอบไปด้วยผู้ประกอบการ เช่นแทนที่จะซีx:=(c|s1|s2) x=c?s1|s2เช่นเดียวกันนี้ใช้กับคำสั่งif & case ¢ BTW: A68 มาจากที่ที่เปลือกรับesac & fi ¢
NevilleDNZ

24

วงเล็บเหลี่ยม[]จะง่ายต่อการพิมพ์นับตั้งแต่IBM 2741สถานีที่ได้รับการ"ที่ใช้กันอย่างแพร่หลายใน Multics" OS ซึ่งจะมีเดนนิสริตชี่หนึ่งในผู้สร้างภาษา C เป็นสมาชิกในทีม dev

http://upload.wikimedia.org/wikipedia/commons/thumb/9/9f/APL-keybd2.svg/600px-APL-keybd2.svg.png

สังเกตการไม่มีวงเล็บปีกกาที่โครงร่าง IBM 2741!

ใน C เครื่องหมายวงเล็บเหลี่ยมจะ "ถูกยึด" เนื่องจากถูกใช้สำหรับอาร์เรย์และพอยน์เตอร์ หากนักออกแบบภาษาคาดว่าอาร์เรย์และพอยน์เตอร์จะมีความสำคัญ / ใช้บ่อยกว่าบล็อคโค้ด (ซึ่งฟังดูเหมือนสมมติฐานที่สมเหตุสมผลที่ด้านข้างของพวกเขามากกว่าในบริบททางประวัติศาสตร์ของรูปแบบการเข้ารหัสด้านล่าง) นั่นหมายความว่า "ไวยากรณ์

ความสำคัญของอาร์เรย์นั้นค่อนข้างชัดเจนในบทความThe Development of the C Languageโดย Ritchie มีแม้กระทั่งสมมติฐานระบุไว้อย่างชัดเจนของ"ความชุกของตัวชี้ในโปรแกรม C"

... ภาษาใหม่รักษาคำอธิบายที่สอดคล้องกันและสามารถใช้งานได้ (ถ้าผิดปกติ) ของความหมายของอาร์เรย์ ... สองความคิดเป็นลักษณะส่วนใหญ่ของ Cในภาษาของระดับ: ความสัมพันธ์ระหว่างอาร์เรย์และตัวชี้ ... คุณสมบัติอื่น ๆ ของ C, การรักษาของอาร์เรย์ ... มีคุณธรรมจริง แม้ว่าความสัมพันธ์ระหว่างพอยน์เตอร์และอาร์เรย์นั้นผิดปกติ แต่ก็สามารถเรียนรู้ได้ ยิ่งไปกว่านั้นภาษาแสดงพลังจำนวนมากในการอธิบายแนวคิดที่สำคัญตัวอย่างเช่นเวกเตอร์ที่มีความยาวแตกต่างกันไปในเวลาทำงานโดยมีกฎพื้นฐานเพียงไม่กี่ข้อและการประชุม ...


เพื่อความเข้าใจเพิ่มเติมเกี่ยวกับบริบททางประวัติศาสตร์และรูปแบบการเข้ารหัสของเวลาที่สร้างภาษา C เราจำเป็นต้องคำนึงว่า"ต้นกำเนิดของ C เชื่อมโยงอย่างใกล้ชิดกับการพัฒนาของ Unix"และโดยเฉพาะอย่างยิ่งการย้ายระบบปฏิบัติการไปยัง PDP- 11 "นำไปสู่การพัฒนารุ่นแรกของ C" ( แหล่งคำพูด ) ตามที่วิกิพีเดีย , "ในปี 1972, Unix ถูกเขียนใหม่ในการเขียนโปรแกรมภาษา C"

ซอร์สโค้ดของ Unix รุ่นเก่า ๆ มีให้บริการออนไลน์เช่นที่เว็บไซต์Unix Tree จากรุ่นต่าง ๆ ที่นำเสนอมีความเกี่ยวข้องมากที่สุดน่าจะเป็นรุ่นที่สอง Unixลงวันที่ 1972-06:

Unix รุ่นที่สองได้รับการพัฒนาสำหรับ PDP-11 ที่ Bell Labs โดย Ken Thompson, Dennis Ritchie และคนอื่น ๆ มันขยายรุ่นแรกด้วยการเรียกระบบและคำสั่งเพิ่มเติม ฉบับนี้ยังเห็นจุดเริ่มต้นของภาษา C ซึ่งใช้ในการเขียนคำสั่งบางอย่าง ...

คุณสามารถเรียกดูและศึกษาซอร์สโค้ด C จากหน้า Second Edition Unix (V2)เพื่อรับทราบแนวคิดของรูปแบบการเข้ารหัสทั่วไปของเวลา

ตัวอย่างที่โดดเด่นที่สนับสนุนแนวคิดที่ย้อนกลับไปแล้วมันค่อนข้างสำคัญสำหรับโปรแกรมเมอร์ที่จะสามารถพิมพ์วงเล็บเหลี่ยมได้อย่างง่ายดายสามารถพบได้ในซอร์สโค้ด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;

เป็นที่น่าสนใจที่จะทราบว่าแรงจูงใจในการใช้งานอย่างจริงจังของการเลือกตัวละครเพื่อแสดงถึงองค์ประกอบทางภาษาตามการใช้งานในแอพพลิเคชั่นเป้าหมายที่มีลักษณะคล้ายกับกฎหมายของ Zipf ดังที่อธิบายไว้ในคำตอบที่ยอดเยี่ยมนี้ ...

ความสัมพันธ์ที่สังเกตได้ระหว่างความถี่และความยาวเรียกว่ากฎของ Zipf

... ด้วยความแตกต่างเพียงอย่างเดียวที่ความยาวในข้อความด้านบนถูกแทนที่ด้วย / generalized เป็นความเร็วในการพิมพ์


5
มีอะไรในการสนับสนุนความคาดหวัง "ชัดเจน" นี้ของนักออกแบบภาษา? ไม่ต้องเขียนโปรแกรมมากใน C เพื่อสังเกตว่าวงเล็บปีกกานั้นเป็นเรื่องธรรมดามากกว่าการประกาศอาเรย์ สิ่งนี้ไม่ได้เปลี่ยนไปมากนักตั้งแต่สมัยโบราณ - ดู K&R

1
ฉันสงสัยในคำอธิบายนี้ เราไม่ทราบว่าสิ่งที่คาดหวังและพวกเขาสามารถเลือกได้อย่างง่ายดายเพราะพวกเขาเป็นคนที่จะตัดสินใจเกี่ยวกับสัญกรณ์อาร์เรย์ เราไม่รู้ด้วยซ้ำว่าพวกเขาคิดว่าเครื่องมือจัดฟันแบบหยิกเป็นตัวเลือกที่ "สำคัญน้อยกว่า" หรือบางทีพวกเขาอาจชอบเครื่องมือจัดฟันแบบหยิกมากกว่า
thorsten müller

3
@gnat: การจัดฟันแบบเหลี่ยมง่ายต่อการพิมพ์บนแป้นพิมพ์ที่ทันสมัยนี่ใช้กับแป้นพิมพ์ที่อยู่รอบ ๆ เมื่อใช้งาน unix และ c หรือไม่? ฉันไม่มีเหตุผลที่จะสงสัยว่าพวกเขากำลังใช้แป้นพิมพ์เดียวกันหรือว่าพวกเขาคิดว่าแป้นพิมพ์อื่น ๆ จะเหมือนกับแป้นพิมพ์ของพวกเขาหรือว่าพวกเขาคิดว่าการพิมพ์ด้วยความเร็วจะคุ้มค่ากับตัวละครตัวหนึ่ง
Michael Shaw

1
นอกจากนี้กฎหมายของ Zipf ยังเป็นลักษณะทั่วไปของสิ่งที่เกิดขึ้นในภาษาธรรมชาติ C ถูกสร้างขึ้นเทียมดังนั้นจึงไม่มีเหตุผลที่จะคิดว่ามันจะใช้ที่นี่เว้นแต่ว่าผู้ออกแบบของ C ตัดสินใจอย่างจงใจที่จะใช้มันโดยเจตนา ถ้ามันใช้มันก็ไม่มีเหตุผลที่จะคิดว่ามันจะทำให้บางสิ่งบางอย่างสั้น ๆ อย่างตัวละครตัวเดียว
Michael Shaw

1
@gnat FWIW grep -Foบอก*.cไฟล์ของซอร์สโค้ด CPython (rev. 4b42d7f288c5 เพราะนั่นคือสิ่งที่ฉันมีอยู่ในมือ) ซึ่งรวมถึง libffi มี 39511 {(39508 {ทำไมไม่วงเล็บปีกกาสองอัน) แต่เพียง 13718 [(13702) [) นั่นคือการนับจำนวนครั้งที่เกิดขึ้นในสตริงและในบริบทที่ไม่เกี่ยวข้องกับคำถามนี้ดังนั้นจึงไม่ถูกต้องจริงๆแม้ว่าเราจะไม่สนใจรหัสฐานอาจไม่ได้เป็นตัวแทน (โปรดสังเกตว่าอคตินี้สามารถไปในทิศทางใดทิศทางหนึ่ง) ยังเป็นปัจจัยที่ 2.8?

1

C (และต่อมา C ++ และ C #) สืบทอดสไตล์การค้ำจุนจากบรรพบุรุษBซึ่งเขียนโดย Ken Thompson (ด้วยการสนับสนุนจาก Dennis Ritchie) ในปี 1969

ตัวอย่างนี้มาจากการอ้างอิงของผู้ใช้ถึง B โดย Ken Thompson (ผ่านWikipedia ):

/* The following function will print a non-negative number, n, to
   the base b, where 2<=b<=10,  This routine uses the fact that
   in the ASCII character set, the digits 0 to 9 have sequential
   code values.  */

printn(n,b) {
        extern putchar;
        auto a;

        if(a=n/b) /* assignment, not test for equality */
                printn(a, b); /* recursive */
        putchar(n%b + '0');
}

B เองนั้นใช้BCPLอีกครั้งซึ่งเป็นภาษาที่เขียนโดย Martin Richards ในปี 1966 สำหรับระบบปฏิบัติการ Multics ระบบการค้ำยันของ B ใช้การจัดฟันแบบกลมเท่านั้นซึ่งแก้ไขโดยอักขระเพิ่มเติม (ตัวอย่างการพิมพ์แฟกทอเรียลโดย Martin Richards ผ่านWikipedia ):

GET "LIBHDR"

LET START() = VALOF $(
        FOR I = 1 TO 5 DO
                WRITEF("%N! = %I4*N", I, FACT(I))
        RESULTIS 0
)$

AND FACT(N) = N = 0 -> 1, N * FACT(N - 1)

วงเล็บปีกกาที่ใช้ใน B และภาษาที่ตามมา "{... }" เป็นการปรับปรุง Ken Thompson ที่ทำขึ้นในรูปแบบวงเล็บปีกกาแบบดั้งเดิมใน BCPL "$ (... ) $"


1
ไม่ดูเหมือนว่า Bob Bemer ( en.wikipedia.org/wiki/Bob_Bemer ) เป็นผู้รับผิดชอบในเรื่องนี้ - "... คุณเสนอว่าพวกเขาสามารถใช้แทนคำหลัก 'เริ่มต้น' และ 'สิ้นสุด' ซึ่งก็คือ วิธีการใช้ภาษา C ในภายหลัง " (จากbobbemer.com/BRACES.HTM )
SChepurin

1
$( ... $)รูปแบบเทียบเท่ากับ{ ... }ใน lexer ใน BCPL เช่นเดียวกับที่??< ... ??>เทียบเท่ากับ{ ... }ใน C. การพัฒนาระหว่างสองรูปแบบคือในฮาร์ดแวร์แป้นพิมพ์ - ไม่ภาษา
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.