เหตุใดเราจึงต้องใช้ argc ในขณะที่มีค่าว่างอยู่ท้าย argv เสมอ


117

ดูเหมือนว่าargv[argc]อยู่เสมอดังนั้นผมคิดว่าเราสามารถสำรวจรายการอาร์กิวเมนต์โดยไม่ต้องNULL ลูปargcเดียวwhileจะทำสิ่งนี้

หากมีการNULLต่อท้ายargvเสมอทำไมเราต้องมีargc?


17
คงเป็นเรื่องของความสะดวก ช่วยให้โปรแกรมเมอร์มีวิธีง่ายๆในการประกันตัวก่อนหากมีข้อโต้แย้งไม่เพียงพอโดยไม่ต้องวนซ้ำ มิฉะนั้นเราจะมีฟังก์ชันที่เรียกว่าint argc(char *argv[])ทำสิ่งนี้อย่างแน่นอน :-))
cnicutar

5
เพื่อให้ชัดเจน"\0"ไม่เหมือนกับตัวชี้ NULL ( 0เทียบเท่ากับ NULL ใน C ++)
Mats Petersson

31
ทำไมเราถึงต้องมี argv [argc] เป็น NULL ถ้าเรามี argc?
Ambroz Bizjak

7
คุณจะกำหนดจำนวนอาร์กิวเมนต์ในเวลาคงที่ได้อย่างไร
avakar

4
อย่าคิดว่าแท็ก linux / unix เหมาะสมที่นี่เนื่องจากพฤติกรรมนี้ควรเป็นจริงสำหรับคอมไพเลอร์ทั้งหมดในระบบปฏิบัติการทั้งหมด
Darrel Hoffman

คำตอบ:


106

ใช่argv[argc]==NULLรับประกัน ดูC11 5.1.2.2.1 การเริ่มต้นโปรแกรม (ฉันเน้น)

หากมีการประกาศพารามิเตอร์ของฟังก์ชันหลักจะต้องปฏิบัติตามข้อ จำกัด ต่อไปนี้:

ค่าของ argc จะต้องไม่เป็นค่าลบ argv [argc] จะเป็นตัวชี้โมฆะ

หาก argcจึงไม่สำคัญ แต่ยังมีประโยชน์ เหนือสิ่งอื่นใดมันช่วยให้ตรวจสอบได้อย่างรวดเร็วว่ามีการส่งผ่านจำนวนอาร์กิวเมนต์ที่ถูกต้องหรือไม่

แก้ไข: คำถามได้รับการแก้ไขให้รวม C ++ n3337 ร่าง3.6.1 ฟังก์ชั่นหลักกล่าวว่า

2 ... argc คือจำนวนอาร์กิวเมนต์ที่ส่งผ่านไปยังโปรแกรมจากสภาพแวดล้อมที่โปรแกรมทำงาน .... ค่าของ argc จะต้องไม่เป็นลบ ค่าของ argv [การ argc] จะเป็น 0


36
และargcอาจจะค่อนข้างใหญ่เพราะเปลือกจะทำการขยายตัว (ดังนั้นในมีการขยายจากเปลือกก่อนการปฏิบัติการ) ในระบบของฉันฉันสามารถมีได้หลายแสน ls **execve/bin/lsargc
Basile Starynkevitch

มันเยี่ยมมากสิ่งนี้ไม่เคยเกิดขึ้นกับฉันเพราะฉันคิดว่าargcเพียงพอเสมอแต่ฉันสามารถนึกถึงสถานการณ์ที่การรับประกันนี้เกี่ยวข้องและจำเป็นได้อย่างแน่นอน +1
Thomas

6
@BasileStarynkevitch เวลาของการก้าวผ่านอาร์เรย์ของค่าตัวชี้หนึ่งครั้งพิเศษจนกว่าจะเป็น NULL เพื่อให้ได้ค่านับเป็นขนาดเล็กเมื่อเทียบกับเวลาที่ใช้ไปแล้วในการสร้างอาร์เรย์ตัวชี้และไม่เกี่ยวข้องมากกว่าเมื่อเทียบกับการใช้ค่าอาร์กิวเมนต์แต่ละค่าในโปรแกรม และถ้าแค่ตรวจสอบว่าจำนวนอาร์กิวเมนต์มากกว่า N ก็ไม่จำเป็นต้องดำเนินการตามอาร์เรย์ทั้งหมด ถึงกระนั้นฉันก็เห็นด้วยอย่างยิ่งนั่นargcคือและเป็นสิ่งที่ดี
hyde

43

ใช่argv[argc]รับประกันว่าจะเป็นตัวชี้โมฆะ argcใช้เพื่อความสะดวก

อ้างคำอธิบายอย่างเป็นทางการจาก C99 Rationale สังเกตคำว่าซ้ำซ้อนตรวจสอบ :

เหตุผลสำหรับมาตรฐานสากล - ภาษาโปรแกรม - C §5.1.2.2.1การเริ่มต้นโปรแกรม

ข้อกำหนดargcและargvเป็นข้อโต้แย้งเพื่อmainรับรู้การปฏิบัติก่อนหน้านี้อย่างกว้างขวาง argv[argc]จำเป็นต้องเป็นตัวชี้ค่าว่างเพื่อให้การตรวจสอบจุดสิ้นสุดของรายการซ้ำซ้อนและบนพื้นฐานของการปฏิบัติทั่วไป


19

ด้วยเหตุผลทางประวัติศาสตร์และความเข้ากันได้กับรหัสเก่า ในขั้นต้นไม่มีการรับประกันว่าจะมีตัวชี้ว่างเป็นองค์ประกอบสุดท้ายของอาร์เรย์ argv แต่ argc มีอยู่เสมอ


... ซึ่งน่าเสียดายในทางหนึ่ง ถ้าเรามีint main(char *argv[], int argc, ...)โปรแกรมบางโปรแกรมก็สามารถละเว้นได้argcเพราะไม่จำเป็นต้องใช้ ตรงข้าม (จำเป็นargcแต่ไม่argv) อาจไม่มีประโยชน์ในโปรแกรมจริง
hyde

@hyde: ดูความคิดเห็นด้านบนโดย Basile Starynkevitch
zentrunix

6

เรา "ต้องการ" เพราะมันจำเป็นตามมาตรฐานต่างๆ

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

#include <stdio.h> // C-compatible include, guarantees puts in global namespace

// program will print contents of argv, one item per line, starting from argv[0]

int main(int /*argc*/, char *argv[]) { // uncomment argc for C

    //(void)argc; // uncomment statement for C

    for (int i=0; argv[i]; ++i) {
        puts(argv[i]);
    }

    return 0;
}

ในมาตรฐาน C ที่มีการตั้งค่าคำเตือนทั่วไปพารามิเตอร์ที่ไม่ได้ใช้จะสร้างคำเตือนซึ่งสามารถแก้ไขได้โดยคำสั่ง(void)argc;ที่ทำให้ชื่อถูกใช้โดยไม่ต้องสร้างรหัสใด ๆ

argcเป็นสิ่งที่ดีที่มีเพราะมิฉะนั้นหลายโปรแกรมจะต้องเดินผ่านพารามิเตอร์เพื่อรับการนับ นอกจากนี้ในภาษาโปรแกรมหลายภาษาที่มีอาร์เรย์ที่มีความยาวไม่มีargcพารามิเตอร์ใด ๆมีเพียงอาร์เรย์ที่มีรายการ


คำถามเกี่ยวกับทั้ง C และ C ++ ใน C ต้องระบุชื่อพารามิเตอร์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.