2010-06-11 78 views
348

Trong của nhiều C++ IDE và trình biên dịch, khi nó tạo ra các chức năng chính cho bạn, nó trông như thế này:int argc, char * argv [] có nghĩa là gì?

int main(int argc, char *argv[]) 

Khi tôi mã C++ mà không có một IDE, chỉ với một trình biên dịch dòng lệnh, tôi gõ:

int main() 

không có bất kỳ thông số nào. Điều này có ý nghĩa gì, và nó có quan trọng đối với chương trình của tôi không?

+35

Nếu chương trình của bạn sẽ bỏ qua đối số dòng lệnh, thì những gì bạn viết là tốt. Nếu chương trình của bạn cần xử lý các đối số dòng lệnh, thì IDE đang làm đúng. –

+17

Một gợi ý cho tin tặc: thử khai báo 'int main (int argc, char * argv [], char * envp [])' và in ra đối số cuối cùng. ';)' – ulidtko

+4

@ulidtko nó không phải là tốt mà bạn đang dạy người mới để giới thiệu tính dễ bị tổn thương trong các chương trình của họ;) –

Trả lời

476

argvargc là cách đối số dòng lệnh được chuyển đến main() trong C và C++.

argc sẽ là số chuỗi được trỏ đến bởi argv. Điều này sẽ (trong thực tế) là 1 cộng với số lượng đối số, vì hầu như tất cả các triển khai sẽ thêm tên chương trình vào mảng.

Các biến được đặt tên argc (luận count) và argv (luận vector) theo quy ước, nhưng họ có thể đưa ra bất kỳ nhận dạng hợp lệ: int main(int num_args, char** arg_strings) là giá trị ngang nhau.

Chúng cũng có thể được bỏ qua hoàn toàn, sinh lợi int main(), nếu bạn không có ý định xử lý đối số dòng lệnh.

Hãy thử chương trình sau đây:

#include <iostream> 

int main(int argc, char** argv) { 
    std::cout << "Have " << argc << " arguments:" << std::endl; 
    for (int i = 0; i < argc; ++i) { 
     std::cout << argv[i] << std::endl; 
    } 
} 

Chạy nó với ./test a1 b2 c3 chí đầu ra

Have 4 arguments: 
./test 
a1 
b2 
c3 
+7

'argc' có thể là 0, trong trường hợp này' argv' có thể là NULL. Nó được cho phép bởi AFAIK chuẩn. Tôi chưa bao giờ nghe nói về một hệ thống thực hiện điều này trong thực tế, nhưng nó chắc chắn có thể tồn tại và sẽ không vi phạm bất kỳ tiêu chuẩn nào. – Chuck

+63

@Chuck: Vì "Giá trị của' argv [argc] 'phải là 0" (C++ 03 §3.6.1/2), 'argv' không thể là rỗng. –

+0

@ James: Ồ, điểm tốt. Tôi đã suy nghĩ về C, trong đó có quy tắc khác nhau tinh tế cho 'chính'. – Chuck

42

argc là số đối số được truyền vào chương trình của bạn từ dòng lệnh và argv là mảng lập luận.

Bạn lặp qua các đối số biết số trong số họ có thể thích:

for(int i = 0; i < argc; i++) 
{ 
    // argv[i] is the argument at index i 
} 
7

Các thông số để chính đại diện cho các thông số dòng lệnh cung cấp cho các chương trình khi nó được bắt đầu. Tham số argc đại diện cho số đối số dòng lệnh và char * argv [] là một mảng các chuỗi (các con trỏ ký tự) biểu diễn các đối số riêng lẻ được cung cấp trên dòng lệnh.

+2

Argv [] luôn luôn có argv [arg] như là một con trỏ null. và Argv [0] luôn luôn là (đường dẫn đầy đủ)/executableName như là một chuỗi bị hủy kết thúc – user3629249

+2

@ user3629249: Không nhất thiết; 'argv [0]' là bất cứ chương trình nào khởi chạy chương trình C đã cho nó như là 'argv [0]'. Trong trường hợp Bash, thường là (có thể luôn luôn) tên đường dẫn của tệp thực thi, nhưng Bash không phải là chương trình duy nhất thực thi các chương trình khác. Nó là permissisble, mặc dù lập dị, để sử dụng: 'char * args [] = {" cat ","/dev/null ","/etc/passwd ", 0}; execv ("/ bin/ls", args); '. Trên nhiều hệ thống, giá trị mà chương trình nhìn thấy là 'argv [0]' sẽ là 'cat', mặc dù thực thi là'/bin/ls'. –

5

Tham số đầu tiên là số đối số được cung cấp và thông số thứ hai là danh sách các chuỗi đại diện cho các đối số đó.

+5

mục nhập đầu tiên trong argv [0] là tên chương trình, không phải là đối số – user3629249

1

Cả hai

int main(int argc, char *argv[]); 
int main(); 

là định nghĩa pháp lý của điểm mấu chốt cho một chương trình C hoặc C++. Stroustrup: C++ Style and Technique FAQ chi tiết một số biến thể có thể hoặc hợp pháp cho chức năng chính của bạn.

+2

Có thể muốn bỏ trống trong ... 'int main()' ==> 'int main (void)' ... để tương thích và dễ đọc . Tôi không biết nếu tất cả các phiên bản cũ của C cho phép các hàm void có một danh sách tham số rỗng trong khai báo. – dylnmc

+1

@dylnmc điều này không cung cấp cho bất kỳ khả năng đọc được, và là chính xác tương đương trong tất cả các phiên bản C++. Chỉ trong C, điều này có một sự khác biệt, nhưng chỉ trong khai báo, không phải trong định nghĩa. – Ruslan

+0

@Ruslan Xin lỗi, tôi đã đăng bài này khi tôi vừa mới học C, và tôi có thể đã đọc rằng trong các phiên bản đầu tiên của C là 'void' là bắt buộc. Đừng nói với tôi về điều đó, và bây giờ tôi biết đó là một nhận xét hơi ngu xuẩn. Tuy nhiên, nó không thể bị tổn thương. – dylnmc

5

Chức năng main thể có hai thông số, argcargv.argc là tham số nguyên và là số đối số được truyền cho chương trình.

tên chương trình luôn là đối số đầu tiên, vì vậy sẽ có ít nhất một đối số cho một chương trình và giá trị tối thiểu là argc sẽ là một. Nhưng nếu một chương trình có hai đối số thì giá trị của argc sẽ là ba.

Tham số argv trỏ đến mảng chuỗi và được gọi là "vector đối số". Nó là mảng chuỗi một chiều của các đối số hàm.

+1

cũng sẽ hữu ích: http://crasseux.com/books/ctutorial/argc-and-argv.html – moshtagh

11

Giả sử bạn chạy chương trình của bạn như vậy (sử dụng sh cú pháp):

myprog arg1 arg2 'arg 3' 

Nếu bạn tuyên bố chính của bạn như int main(int argc, char *argv[]), sau đó (trong hầu hết các môi trường), main() của bạn sẽ được gọi là nếu như:

p = { "myprog", "arg1", "arg2", "arg 3", NULL }; 
exit(main(4, p)); 

Tuy nhiên, nếu bạn tuyên bố chính của bạn như int main(), nó sẽ được gọi là một cái gì đó giống như

exit(main()); 

và bạn không nhận được đối số được chuyển.

Hai điều bổ sung cần lưu ý:

  1. Đây là hai chữ ký tiêu chuẩn bắt buộc chỉ cho main. Nếu một nền tảng cụ thể chấp nhận các đối số thừa hoặc một kiểu trả về khác, thì đó là một phần mở rộng và không nên dựa vào trong một chương trình di động.
  2. *argv[]**argv tương đương chính xác, vì vậy bạn có thể viết int main(int argc, char *argv[]) làm int main(int argc, char **argv).
+1

Nếu chúng tôi đang là kỹ thuật, ['basic.start.main/2'] (https://timsong-cpp.github.io/cppwp/basic.start.main#2) cho phép rõ ràng các phiên bản bổ sung được triển khai thực hiện của 'main()', miễn là việc triển khai cung cấp hai phiên bản được xác định trước. Vì vậy, chúng không _exactly_ không phù hợp. Một trong những phổ biến nhất là 'envp', mà là rất nổi tiếng trong cả C và C + + rằng [nó theo nghĩa đen là mục đầu tiên trong phần J.5 (Common extensions) của tiêu chuẩn C] (http://port70.net /~nsz/c/c11/n1570.html#J.5). –

+0

Cảm ơn bạn đã giúp đỡ tốt đẹp @Justin. Trả lời được cập nhật để chính xác hơn. –

+0

@TobySpeight \t nếu argc <3 trả về lỗi thì sao? những gì có thể có thể đi sai? – AVI

1
int main(); 

Đây là tuyên bố đơn giản. Nó không thể lấy bất kỳ đối số dòng lệnh nào.

int main(int argc, char* argv[]); 

Tuyên bố này được sử dụng khi chương trình của bạn phải có đối số dòng lệnh. Khi chạy như ví dụ:

myprogram arg1 arg2 arg3 

argc, hoặc Đếm Đối số, sẽ được thiết lập đến 4 (bốn đối số), và argv, hoặc Vectors Đối số, sẽ được áp dụng với con trỏ chuỗi để "myprogram", "arg1", "arg2" và "arg3". Gọi chương trình (myprogram) được bao gồm trong các đối số!

Ngoài ra, bạn có thể sử dụng:

int main(int argc, char** argv); 

Đây cũng là hợp lệ.

Có một tham số bạn có thể thêm:

int main (int argc, char *argv[], char *envp[]) 

Tham số envp cũng chứa các biến môi trường. Mỗi mục sau định dạng này:

VARIABLENAME=VariableValue 

như thế này:

SHELL=/bin/bash  

Môi trường danh sách các biến là null-chấm dứt.

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