ในสมัยเรียนมหาวิทยาลัยฉันอ่านเกี่ยวกับauto
คีย์เวิร์ดและในบางครั้งฉันก็ลืมไปว่ามันคืออะไร ถูกกำหนดให้เป็น:
กำหนดตัวแปรโลคัลว่ามีอายุการใช้งานโลคัล
ไม่เคยพบว่ามีการใช้งานที่ไหนมีการใช้งานจริงหรือไม่และถ้าเป็นเช่นนั้นจะใช้ที่ไหนและในกรณีใด
ในสมัยเรียนมหาวิทยาลัยฉันอ่านเกี่ยวกับauto
คีย์เวิร์ดและในบางครั้งฉันก็ลืมไปว่ามันคืออะไร ถูกกำหนดให้เป็น:
กำหนดตัวแปรโลคัลว่ามีอายุการใช้งานโลคัล
ไม่เคยพบว่ามีการใช้งานที่ไหนมีการใช้งานจริงหรือไม่และถ้าเป็นเช่นนั้นจะใช้ที่ไหนและในกรณีใด
คำตอบ:
auto
เป็นตัวปรับแต่งเช่นstatic
. เป็นการกำหนดคลาสการจัดเก็บของตัวแปร อย่างไรก็ตามเนื่องจากค่าเริ่มต้นสำหรับตัวแปรในระบบคือauto
โดยปกติคุณไม่จำเป็นต้องระบุด้วยตนเอง
หน้านี้แสดงรายการพื้นที่จัดเก็บข้อมูลต่างๆใน C
auto
. tigcc.ticalc.org/doc/keywords.html#auto
_Thread_local
รายละเอียด: en.cppreference.com/w/c/language/storage_durationและstackoverflow.com/a/14289720/6557621
หากคุณอ่านรายการIAQ (คำถามที่ถามบ่อย) คุณจะทราบดีว่ารถยนต์มีประโยชน์ในการกำหนดหรือประกาศยานพาหนะเป็นหลัก:
auto my_car;
ยานพาหนะที่จอดกลางแจ้งเป็นประจำ:
extern auto my_car;
สำหรับผู้ที่ไม่มีอารมณ์ขันและต้องการ "คำตอบที่เป็นข้อเท็จจริง" คำตอบสั้น ๆ คือไม่เคยมีเหตุผลใด ๆ ที่จะใช้auto
เลย เวลาเดียวที่คุณได้รับอนุญาตให้ใช้auto
คือตัวแปรที่มีauto
คลาสพื้นที่เก็บข้อมูลอยู่แล้วดังนั้นคุณเพียงแค่ระบุบางสิ่งที่จะเกิดขึ้นต่อไป การพยายามใช้auto
กับตัวแปรใด ๆ ที่ไม่มีauto
คลาสหน่วยเก็บข้อมูลอยู่แล้วจะส่งผลให้คอมไพเลอร์ปฏิเสธโค้ดของคุณ ฉันคิดว่าถ้าคุณต้องการได้รับทางเทคนิคการใช้งานของคุณไม่จำเป็นต้องเป็นคอมไพเลอร์ (แต่เป็น) และในทางทฤษฎีสามารถรวบรวมโค้ดต่อไปได้หลังจากออกการวินิจฉัย (แต่จะไม่ได้)
ภาคผนวกเล็ก ๆ โดยkaz :
นอกจากนี้ยังมี:
static auto my_car;
ซึ่งต้องได้รับการตรวจวินิจฉัยตามมาตรฐาน ISO C ซึ่งถูกต้องเนื่องจากมีการประกาศว่ารถเสีย การวินิจฉัยไม่มีค่าใช้จ่าย แต่การปิดไฟแดชบอร์ดจะทำให้คุณเสียค่าใช้จ่ายแปดสิบเหรียญ (ยี่สิบหรือน้อยกว่าหากคุณซื้อดองเกิล USB ของคุณเองสำหรับการวินิจฉัยออนบอร์ดจาก eBay)
ดังกล่าวข้างต้นextern auto my_car
ยังต้องการการวินิจฉัยและด้วยเหตุนี้จึงไม่มีการเรียกใช้ผ่านคอมไพเลอร์นอกจากโดยเจ้าหน้าที่ของเมืองที่ได้รับมอบหมายให้บังคับใช้ที่จอดรถ
หากคุณเห็นจำนวนมากextern static auto ...
ในฐานรหัสใด ๆ แสดงว่าคุณอยู่ในย่านที่ไม่ดี มองหางานที่ดีกว่าทันทีก่อนที่ทั้งสถานที่จะเปลี่ยนเป็น Rust
char auto my_car;
auto
คำหลักจะไม่ได้ผลในภาษา C เป็นเพราะก่อนหน้านี้ภาษา C มีภาษา B ซึ่งคำหลักนั้นจำเป็นสำหรับการประกาศตัวแปรท้องถิ่น (B ได้รับการพัฒนาเป็น NB ซึ่งกลายเป็น C)
นี่คือคู่มืออ้างอิงสำหรับ B
อย่างที่คุณเห็นคู่มือนี้เต็มไปด้วยตัวอย่างที่auto
ใช้ เป็นเช่นนี้เนื่องจากไม่มีint
คีย์เวิร์ด คำหลักบางประเภทจำเป็นต้องพูดว่า "นี่คือการประกาศตัวแปร" และคำหลักนั้นยังระบุด้วยว่าเป็นคำหลักภายในหรือภายนอก ( auto
เทียบกับextrn
) หากคุณไม่ได้ใช้อย่างใดอย่างหนึ่งแสดงว่าคุณมีข้อผิดพลาดทางไวยากรณ์ กล่าวx, y;
คือไม่ใช่การประกาศด้วยตัวเอง แต่auto x, y;
เป็นการประกาศ
เนื่องจากรหัสฐานที่เขียนด้วย B จะต้องย้ายไปที่ NB และ C เมื่อภาษาได้รับการพัฒนาภาษาเวอร์ชันใหม่กว่าจึงมีสัมภาระบางส่วนเพื่อให้เข้ากันได้ย้อนหลังได้ดีขึ้นซึ่งแปลว่าใช้งานได้น้อยลง ในกรณีของauto
โปรแกรมเมอร์ไม่จำเป็นต้องค้นหาทุกเหตุการณ์ที่เกิดขึ้นauto
และลบออก
เห็นได้ชัดจากคู่มือว่าตอนนี้ "implicit int" ที่ล้าสมัยใน C (ความสามารถในการเขียนmain() { ... }
โดยไม่ต้องมีint
ด้านหน้า) มาจาก B. นั่นคือคุณสมบัติความเข้ากันได้แบบย้อนกลับอีกอย่างหนึ่งเพื่อรองรับรหัส B ฟังก์ชันไม่มีประเภทการส่งคืนที่ระบุใน B เนื่องจากไม่มีประเภท ทุกอย่างเป็นคำเช่นเดียวกับในภาษาแอสเซมบลีหลายภาษา
สังเกตว่าฟังก์ชันสามารถประกาศได้อย่างไรextrn putchar
จากนั้นสิ่งเดียวที่ทำให้เป็นฟังก์ชันที่ตัวระบุใช้ : มันถูกใช้ในนิพจน์การเรียกฟังก์ชันเช่นputchar(x)
และนั่นคือสิ่งที่บอกให้คอมไพเลอร์ถือว่าคำที่ไม่มีประเภทนั้นเป็นตัวชี้ฟังก์ชัน
ใน C auto
คือคีย์เวิร์ดที่บ่งชี้ว่าตัวแปรเป็นแบบโลคัลสำหรับบล็อก เนื่องจากเป็นค่าเริ่มต้นสำหรับตัวแปร block-scoped จึงไม่จำเป็นและใช้น้อยมาก (ฉันไม่คิดว่าฉันเคยเห็นมันใช้นอกตัวอย่างในข้อความที่พูดถึงคำหลัก) ฉันจะสนใจว่ามีใครสามารถชี้ให้เห็นถึงกรณีที่auto
จำเป็นต้องใช้เพื่อให้ได้การแยกวิเคราะห์หรือพฤติกรรมที่ถูกต้อง
อย่างไรก็ตามในมาตรฐาน C ++ 11 auto
คำหลักถูก 'จี้' เพื่อสนับสนุนการอนุมานประเภทโดยที่ประเภทของตัวแปรสามารถนำมาจากประเภทของตัวเริ่มต้น:
auto someVariable = 1.5; // someVariable will have type double
การอนุมานประเภทส่วนใหญ่จะถูกเพิ่มเพื่อสนับสนุนการประกาศตัวแปรในเทมเพลตหรือส่งคืนจากฟังก์ชันเทมเพลตโดยที่ประเภทตามพารามิเตอร์เทมเพลต (หรือสรุปโดยคอมไพเลอร์เมื่อเทมเพลตถูกสร้างอินสแตนซ์) มักจะค่อนข้างเจ็บปวดในการประกาศด้วยตนเอง
auto
เป็นเรื่องเกี่ยวกับคลาสพื้นที่เก็บข้อมูลซึ่งไม่มีส่วนเกี่ยวข้องกับการมองเห็น
ด้วยคอมไพเลอร์ Aztec C แบบเก่ามันเป็นไปได้ที่จะเปลี่ยนตัวแปรอัตโนมัติทั้งหมดให้เป็นตัวแปรคงที่ (เพื่อเพิ่มความเร็วในการกำหนดแอดเดรส) โดยใช้สวิตช์บรรทัดคำสั่ง
แต่ตัวแปรที่ประกาศไว้อย่างชัดเจนauto
ถูกปล่อยทิ้งไว้ตามที่เป็นอยู่ในกรณีนั้น (จำเป็นสำหรับฟังก์ชันเรียกซ้ำซึ่งจะทำงานไม่ถูกต้อง!)
auto
คำหลักจะคล้ายกับการรวมของอัฒภาคในหลามมันก็จำเป็นโดยภาษาก่อนหน้า ( B
) auto
แต่นักพัฒนารู้ว่ามันเป็นสิ่งที่ซ้ำซ้อนเนื่องจากส่วนใหญ่เป็น
ฉันสงสัยว่ามันถูกทิ้งไว้เพื่อช่วยในการเปลี่ยนจาก B เป็น C ในระยะสั้นการใช้งานหนึ่งสำหรับความเข้ากันได้ของภาษา B
ตัวอย่างเช่นใน B และ 80 C:
/* 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) {
extrn putchar;
auto a;
if (a = n / b) /* assignment, not test for equality */
printn(a, b); /* recursive */
putchar(n % b + '0');
}
คำสำคัญอัตโนมัติคือคลาสพื้นที่จัดเก็บ (เทคนิคบางอย่างที่ตัดสินอายุการใช้งานของตัวแปรและสถานที่จัดเก็บ) มีลักษณะการทำงานที่ตัวแปรที่ทำโดย Help ของคำหลักนั้นมีอายุการใช้งาน (อายุการใช้งาน) อยู่ภายในวงเล็บปีกกาเท่านั้น
{
auto int x=8;
printf("%d",x); // here x is 8
{
auto int x=3;
printf("%d",x); // here x is 3
}
printf("%d",x); // here x is 8
}
auto
สามารถใช้ได้กับตัวแปรที่กำหนดขอบเขตบล็อกเท่านั้น extern auto int
เป็นขยะเนื่องจากคอมไพเลอร์ไม่สามารถระบุได้ว่าสิ่งนี้ใช้คำจำกัดความภายนอกหรือไม่หรือจะแทนที่ภายนอกด้วยคำจำกัดความอัตโนมัติ (อัตโนมัติและภายนอกก็มีระยะเวลาการจัดเก็บที่แตกต่างกันโดยสิ้นเชิงเช่นstatic auto int
ซึ่งเห็นได้ชัดว่าเป็นขยะด้วย) มันสามารถเลือกตีความแบบเดียวได้เสมอ แต่เลือกที่จะถือว่าเป็นข้อผิดพลาดแทน
มีคุณลักษณะหนึ่งที่มีauto
ให้และเปิดใช้งานกฎ 'everything is an int' ภายในฟังก์ชัน ซึ่งแตกต่างจากภายนอกของฟังก์ชันซึ่งa=3
ถูกตีความว่าเป็นคำจำกัดความint a =3
เนื่องจากไม่มีการกำหนดที่ขอบเขตไฟล์a=3
เป็นข้อผิดพลาดภายในฟังก์ชันเนื่องจากเห็นได้ชัดว่าคอมไพเลอร์ตีความว่าเป็นการกำหนดให้กับตัวแปรภายนอกมากกว่าคำจำกัดความ (แม้ว่าจะมี จะไม่มีextern int a
การประกาศไปข้างหน้าในการทำงานหรือในขอบเขตไฟล์) แต่ระบุเช่นstatic
, const
, volatile
หรือauto
จะบ่งบอกว่ามันคือความหมายและคอมไพเลอร์จะใช้เวลาเป็นคำนิยามยกเว้นauto
ไม่ได้มีผลข้างเคียงของ specifiers อื่น ๆ ดังนั้นจึงเป็นไปโดยปริยายauto a=3
auto int a = 3
เป็นที่ยอมรับsigned a = 3
มีผลเหมือนกันและunsigned a = 3
เป็น int ที่ไม่ได้ลงนามเสมอ
โปรดทราบว่า ' auto
ไม่มีผลกระทบต่อว่าวัตถุจะถูกจัดสรรให้กับรีจิสเตอร์หรือไม่ (เว้นแต่คอมไพเลอร์บางตัวจะให้ความสนใจกับมัน แต่ดูเหมือนว่าไม่น่าเป็นไปได้)'
ฉันแน่ใจว่าคุณคุ้นเคยกับตัวระบุคลาสพื้นที่เก็บข้อมูลใน C ซึ่ง ได้แก่ "extern" "static" "register" และ "auto" คำจำกัดความของ "auto" มีให้ในคำตอบอื่น ๆ ค่อนข้างมาก แต่นี่คือการใช้คีย์เวิร์ด "auto" ที่เป็นไปได้ซึ่งฉันไม่แน่ใจ แต่ฉันคิดว่ามันขึ้นอยู่กับคอมไพเลอร์ คุณจะเห็นว่าเกี่ยวกับตัวระบุคลาสพื้นที่จัดเก็บมีกฎอยู่ เราไม่สามารถใช้ตัวระบุคลาสหน่วยเก็บข้อมูลหลายตัวสำหรับตัวแปรได้ นั่นคือเหตุผลที่ตัวแปรส่วนกลางแบบคงที่ไม่สามารถถูกแทนที่ได้ ดังนั้นจึงรู้จักเฉพาะไฟล์ของพวกเขา เมื่อคุณไปที่การตั้งค่าคอมไพเลอร์ของคุณคุณสามารถเปิดใช้แฟล็กการเพิ่มประสิทธิภาพเพื่อความเร็ว วิธีหนึ่งที่คอมไพเลอร์ปรับให้เหมาะสมคือ ค้นหาตัวแปรที่ไม่มีตัวระบุคลาสหน่วยเก็บข้อมูลจากนั้นทำการประเมินตามความพร้อมใช้งานของหน่วยความจำแคชและปัจจัยอื่น ๆ เพื่อดูว่าควรปฏิบัติต่อตัวแปรนั้นโดยใช้ตัวระบุรีจิสเตอร์หรือไม่ ทีนี้จะเกิดอะไรขึ้นถ้าเราต้องการเพิ่มประสิทธิภาพโค้ดของเราเพื่อความเร็วในขณะที่รู้ว่าตัวแปรเฉพาะในโปรแกรมของเราไม่สำคัญมากนักและเราไม่ต้องการให้คอมไพเลอร์พิจารณามันเป็นรีจิสเตอร์ด้วยซ้ำ แม้ว่าโดยการใส่ auto คอมไพเลอร์จะไม่สามารถเพิ่ม register specifier ให้กับตัวแปรได้เนื่องจากพิมพ์ "register auto int a;" หรือ "auto register int a;" ทำให้เกิดข้อผิดพลาดในการใช้ตัวระบุคลาสหน่วยเก็บข้อมูลหลายตัว สรุปแล้วฉันคิดว่า auto สามารถห้ามไม่ให้คอมไพเลอร์ปฏิบัติต่อตัวแปรเป็นรีจิสเตอร์ผ่านการเพิ่มประสิทธิภาพ จะเป็นอย่างไรหากเราต้องการเพิ่มประสิทธิภาพโค้ดของเราเพื่อความเร็วในขณะที่รู้ว่าตัวแปรเฉพาะในโปรแกรมของเราไม่สำคัญมากนักและเราไม่ต้องการให้คอมไพเลอร์พิจารณาว่าเป็นรีจิสเตอร์ แม้ว่าโดยการใส่ auto คอมไพเลอร์จะไม่สามารถเพิ่ม register specifier ให้กับตัวแปรได้เนื่องจากพิมพ์ "register auto int a;" หรือ "auto register int a;" ทำให้เกิดข้อผิดพลาดในการใช้ตัวระบุคลาสหน่วยเก็บข้อมูลหลายตัว สรุปแล้วฉันคิดว่า auto สามารถห้ามไม่ให้คอมไพเลอร์ปฏิบัติต่อตัวแปรเป็นรีจิสเตอร์ผ่านการเพิ่มประสิทธิภาพ จะเป็นอย่างไรหากเราต้องการเพิ่มประสิทธิภาพโค้ดของเราเพื่อความเร็วในขณะที่รู้ว่าตัวแปรเฉพาะในโปรแกรมของเรานั้นไม่สำคัญมากนักและเราไม่ต้องการให้คอมไพเลอร์พิจารณามันเป็นรีจิสเตอร์ด้วยซ้ำ แม้ว่าโดยการใส่ auto คอมไพเลอร์จะไม่สามารถเพิ่ม register specifier ให้กับตัวแปรได้เนื่องจากพิมพ์ "register auto int a;" หรือ "auto register int a;" ทำให้เกิดข้อผิดพลาดในการใช้ตัวระบุคลาสหน่วยเก็บข้อมูลหลายตัว สรุปแล้วฉันคิดว่า auto สามารถห้ามไม่ให้คอมไพเลอร์ปฏิบัติต่อตัวแปรเป็นรีจิสเตอร์ผ่านการเพิ่มประสิทธิภาพ ทำให้เกิดข้อผิดพลาดในการใช้ตัวระบุคลาสหน่วยเก็บข้อมูลหลายตัว สรุปแล้วฉันคิดว่า auto สามารถห้ามไม่ให้คอมไพเลอร์ปฏิบัติต่อตัวแปรเป็นรีจิสเตอร์ผ่านการเพิ่มประสิทธิภาพ ทำให้เกิดข้อผิดพลาดในการใช้ตัวระบุคลาสหน่วยเก็บข้อมูลหลายตัว สรุปแล้วฉันคิดว่า auto สามารถห้ามไม่ให้คอมไพเลอร์ปฏิบัติต่อตัวแปรเป็นรีจิสเตอร์ผ่านการเพิ่มประสิทธิภาพ
ทฤษฎีนี้ใช้ไม่ได้กับคอมไพเลอร์ GCC แต่ฉันไม่ได้ลองคอมไพเลอร์อื่น
auto
สามารถระบุได้จริง แต่จะไม่เกิดขึ้นตามค่าเริ่มต้นหรือไม่?