Tại sao chúng ta cần argc trong khi luôn có giá trị rỗng ở cuối argv?


116

Có vẻ như argv[argc]luôn luôn NULLnhư vậy, vì vậy tôi nghĩ chúng ta có thể xem qua danh sách đối số mà không cần argc. Một whilevòng lặp duy nhất sẽ làm điều này.

Nếu luôn có một NULLở cuối argv, tại sao chúng ta cần một argc?


17
Nó có lẽ là một vấn đề thuận tiện. Cung cấp cho lập trình viên một cách dễ dàng để giải cứu sớm nếu không có đủ đối số mà không cần lặp lại. Nếu không, chúng tôi chắc chắn sẽ có chức năng gọi là int argc(char *argv[])làm chính xác này :-))
cnicutar

5
Chỉ cần được rõ ràng "\0"là không giống như con trỏ NULL ( 0tương đương với NULL trong C ++)
Thảm Petersson

31
Tại sao chúng ta cần argv [argc] là NULL nếu chúng ta có argc?
Ambroz Bizjak,

7
Làm cách nào khác mà bạn xác định số lượng đối số trong thời gian không đổi?
avakar,

4
Đừng nghĩ rằng các thẻ linux / unix là thích hợp ở đây, vì hành vi này phải đúng với tất cả các trình biên dịch trong tất cả các hệ điều hành.
Darrel Hoffman,

Câu trả lời:


106

Có, argv[argc]==NULLđược đảm bảo. Xem C11 5.1.2.2.1 Khởi động chương trình (tôi nhấn mạnh)

Nếu chúng được khai báo, các tham số của hàm chính sẽ tuân theo các ràng buộc sau:

Giá trị của argc sẽ không âm. argv [argc] sẽ là một con trỏ null.

argcDo đó, việc cung cấp không quan trọng nhưng vẫn hữu ích. Trong số những thứ khác, nó cho phép kiểm tra nhanh xem số lượng đối số chính xác đã được truyền chưa.

Chỉnh sửa: Câu hỏi đã được sửa đổi để bao gồm C ++. n3337 bản nháp 3.6.1 Chức năng chính cho biết

2 ... argc sẽ là số đối số được truyền đến chương trình từ môi trường mà chương trình được chạy. .... Giá trị của argc sẽ không âm. Giá trị của argv [argc] sẽ là 0 .


36
argccó thể là khá lớn, bởi vì vỏ được làm mở rộng (như vậy trong ls *những *được mở rộng bởi lớp vỏ trước execvecủa /bin/lsthực thi). Trên hệ thống của tôi, tôi có thể có argcvài trăm nghìn.
Basile Starynkevitch,

Điều đó khá tuyệt, điều này chưa bao giờ xảy ra với tôi vì tôi luôn coi là argcđủ, nhưng tôi chắc chắn có thể nghĩ đến những tình huống mà sự đảm bảo này sẽ phù hợp và thậm chí là bắt buộc. +1
Thomas

6
@BasileStarynkevitch Thời gian chỉ lướt qua một mảng giá trị con trỏ thêm một lần nữa cho đến khi NULL, để lấy số đếm, là rất nhỏ so với thời gian đã dành để tạo mảng con trỏ và thậm chí còn không liên quan hơn so với việc thực sự sử dụng từng giá trị đối số trong chương trình. Và nếu chỉ kiểm tra xem số đối số có nhiều hơn N hay không, thì không cần xem xét toàn bộ mảng. Tuy nhiên, tôi hoàn toàn đồng ý, đó argclà và là một điều tốt.
hyde

43

Có, argv[argc]được đảm bảo là một con trỏ rỗng. argcđược sử dụng để thuận tiện.

Trích dẫn lời giải thích chính thức từ C99 Rationale, lưu ý các từ kiểm tra thừa :

Cơ sở lý luận về Tiêu chuẩn Quốc tế - Ngôn ngữ Lập trình - C §5.1.2.2.1 Khởi động chương trình

Đặc điểm kỹ thuật của argcargvnhư các đối số để maincông nhận thực tiễn rộng rãi trước đây. argv[argc]được yêu cầu là một con trỏ null để cung cấp một kiểm tra dư thừa cho phần cuối của danh sách, cũng trên cơ sở thông lệ.


19

Đó là vì lý do lịch sử và khả năng tương thích với mã cũ. Ban đầu, không có gì đảm bảo rằng sẽ tồn tại một con trỏ null là phần tử cuối cùng của mảng argv. Nhưng argc vẫn luôn tồn tại.


... Đó là một điều đáng xấu hổ, theo một cách nào đó. Nếu chúng ta đã có int main(char *argv[], int argc, ...), thì một số chương trình có thể bỏ qua argcbởi vì họ không cần nó. Đối lập (cần argcnhưng không argv) có lẽ không bao giờ hữu ích trong một chương trình thực tế.
hyde

@hyde: xem bình luận trên bằng cách Basile Starynkevitch
zentrunix

6

Chúng tôi "cần" nó, bởi vì nó được yêu cầu bởi nhiều tiêu chuẩn khác nhau.

Chúng ta có thể hoàn toàn bỏ qua giá trị, nhưng vì nó là tham số đầu tiên của main, nên chúng ta phải có nó trong danh sách tham số. Trong C ++ (và có thể là phương ngữ C không chuẩn), bạn chỉ có thể bỏ qua tên tham số, như đoạn mã C ++ này (dễ chuyển đổi sang 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;
}

Trong tiêu chuẩn C, với các cài đặt cảnh báo phổ biến, tham số không sử dụng tạo ra cảnh báo, có thể được sửa bằng một câu lệnh như (void)argc;nguyên nhân tên được sử dụng mà không cần tạo bất kỳ mã nào.

argcrất tốt để có, bởi vì nếu không nhiều chương trình sẽ cần phải đi qua các tham số để có được số lượng. Ngoài ra, trong nhiều ngôn ngữ lập trình với mảng có độ dài, không có bất kỳ argctham số nào , chỉ có một mảng với các mục.


Câu hỏi là về cả C và C ++. Trong C, tên tham số là bắt buộc.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.