2015-08-13 12 views
10

Tôi luôn luôn nghĩ rằng argc là cần thiết để đánh dấu sự kết thúc của argv nhưng tôi chỉ biết rằng argv[argc] == NULL theo định nghĩa. Tôi có nghĩ rằng argc là hoàn toàn dư thừa? Nếu vậy, tôi luôn nghĩ rằng C được tạo ra với sự dư thừa về tên hiệu quả. Giả định của tôi sai hay có lý do lịch sử đằng sau điều này? Nếu lý do là lịch sử, bạn có thể xây dựng?Tại sao chính (int argc, char * argv []) có hai đối số?

+1

Không thể 'NULL' là một yếu tố của 'argv'? Đó là, trước khi kết thúc thực tế của mảng. –

+4

@AndrasDeak, tôi không nghĩ vậy. Một phần tử 'argv' có thể là một chuỗi rỗng, đó là một mảng chỉ một phần tử, một' 0'-byte. –

+4

Có nó là dư thừa. Lý do là "lý do lịch sử" –

Trả lời

6

Lịch sử.

Harbison & thép (5th Edition, 9.9 "Các chương trình chính") nói như sau:

Chuẩn C đòi hỏi argv[argc] là một con trỏ null, nhưng nó không phải là như vậy trong một số triển khai lớn tuổi.

+0

Sẽ rất hữu ích khi có một số dấu hiệu 'triển khai cũ hơn' không có 'argv [argc]' con trỏ - Tôi nghi ngờ H & S không cung cấp mức độ chi tiết đó. Họ sẽ phải khá già trong những ngày này. (Tôi đã không bao giờ đủ may mắn để đi qua một, nhưng có rất nhiều nền tảng bí truyền mà tôi đã không được lập trình trên.) –

+0

FWIW Tôi quản lý để tìm một PDF quét của K & R 1st ed., Và theo như tôi có thể nói với họ không bao giờ đề cập đến một sentinel null tại 'argv [argc]' và tất cả các ví dụ sử dụng 'argc' để xác định anh ta kết thúc mảng' argv [] '. Phiên bản thứ 2 chỉ ra các sentinel null, nhưng không sử dụng nó trong bất kỳ ví dụ. –

3

Đây là lịch sử.

Trong ấn bản đầu tiên UNIX, trước đó C, exec lấy làm đối số tên tệp và địa chỉ của danh sách con trỏ tới chuỗi đối số được kết thúc bằng con trỏ NULL. Từ trang người đàn ông:

sys exec; name; args /exec = 11. 
name: <...\0> 
... 
args: arg1; arg2; ...; 0 
arg1: <...\0> 
... 

Kernel tính lên những lập luận và cung cấp hình ảnh mới với các tính arg theo sau là một danh sách các con trỏ đến các bản sao của chuỗi đối số, ở phía trên cùng của ngăn xếp. Từ trang người đàn ông:

sp--> nargs 
     arg1 
     ... 
     argn 

arg1: <arg1\0> 
... 
argn: <argn\0> 

(Nguồn hạt nhân là here; Tôi đã không nhìn thấy nếu hạt nhân thực sự đã viết một cái gì đó sau khi con trỏ đến đối số cuối cùng.)

Tại một số điểm, tăng thông qua ấn bản thứ 6, tài liệu cho exec, execl và execv bắt đầu lưu ý rằng hạt nhân đã đặt một số -1 sau con trỏ arg. Man page nói:

argv là không trực tiếp sử dụng trong execv khác, vì argv [argc] là -1 và không 0.

Tại thời điểm này, bạn có thể tranh luận rằng argc là dư thừa, nhưng các chương trình đã, trong một thời gian, đã sử dụng nó thay vì xem qua danh sách đối số cho -1. Ví dụ, đây là sự khởi đầu của cal.c:

main(argc, argv) 
char *argv[]; 
{ 
    if(argc < 2) { 
     printf("usage: cal [month] year\n"); 
     exit(); 
    } 

Trong ấn bản lần thứ 7, exec được thay đổi để thêm một con trỏ NULL sau chuỗi đối số, và điều này đã được theo sau bởi một danh sách các con trỏ đến chuỗi môi trường, và NULL khác . Man page nói:

argv là sử dụng trực tiếp trong execv khác vì argv [argc] là 0.

Các vấn đề liên quan