Có an toàn để đổi tên argc và argv trong chức năng chính không?


82

Rất nhiều chương trình sử dụng tên chuẩn cho một số đối số và mảng chuỗi. Nguyên mẫu của vẻ chức năng chính như: int main(int argc, char *argv[]);. Nhưng tôi có phá vỡ điều gì đó nếu tôi chọn tên tùy chỉnh cho các biến này không?

Ví dụ int main(int n_of_args, char *args[]);

Trong bối cảnh của trình biên dịch, mọi thứ đều ổn. Các biến này là cục bộ cho hàm main, vì vậy chúng có thể có bất kỳ tên nào. Và mã đơn giản xây dựng và chạy hoàn hảo. Nhưng những tên này có thể được sử dụng bởi bộ tiền xử lý. Vì vậy, nó là an toàn để đổi tên các đối số này?

PS Cá nhân tôi thấy những cái tên này không hay, bởi vì chúng trông rất giống nhau và chỉ khác một chữ cái. Nhưng MỌI NGƯỜI sử dụng chúng vì một số loại lý do.


21
Có, hoàn toàn an toàn.
David Hoelzer

55
Như tất cả các câu trả lời, có, nó an toàn. Nhưng xin đừng làm vậy. Mọi người đều biết những gì argcargvđang có. n_of_argsargscó thể rõ ràng hơn đối với người không biết C hoặc C ++ - nhưng đó không phải là đối tượng của bạn.
Keith Thompson

4
Bạn có thể làm điều này, nó không đủ lý do để làm điều này. Mọi người đều biết những điều đó là gì, và họ mong đợi họ sẽ như vậy.
SergeyA

10
Nếu câu hỏi là chính xác "Tôi sẽ phá vỡ một cái gì đó nếu tôi chọn tên tùy chỉnh", so với câu trả lời chính xác là "có, bạn sẽ phá vỡ truyền thống cũng giải quyết";)
Frax

12
Chỉ cần lật chúng! .. và ngay từ đầu bạn đang đặt nền tảng cho sự an toàn trong công việc :)
yano

Câu trả lời:


121

Có, nó là an toàn, miễn là bạn sử dụng tên biến hợp lệ. Chúng là các biến cục bộ, vì vậy phạm vi của chúng không vượt ra ngoài mainhàm.

Từ phần 5.1.2.2.1 của tiêu chuẩn C :

Chức năng được gọi khi khởi động chương trình được đặt tên main. Việc thực hiện tuyên bố không có nguyên mẫu nào cho chức năng này. Nó sẽ được định nghĩa với kiểu trả về intvà không có tham số:

int main(void) { /*  ... */ }

hoặc với hai tham số (ở đây được gọi là argcargv, mặc dù bất kỳ tên nào cũng có thể được sử dụng, vì chúng là cục bộ cho hàm mà chúng được khai báo ):

int main(int argc, char *argv[]) { /* ...   */ }

hoặc tương đương; hoặc theo một số cách thức triển khai khác được xác định

Điều đó đang được nói, sử dụng bất kỳ thứ gì khác ngoài argcargvcó thể gây nhầm lẫn cho những người khác đang đọc mã của bạn, những người đã quen với tên thông thường cho các tham số này. Vì vậy, tốt hơn nên sai lầm về phía yêu cầu bồi thường.


38

Tên argcargvthực sự được yêu cầu bởi tiêu chuẩn C ++ trước C ++ 11. Nó tuyên bố:

Tất cả các triển khai sẽ cho phép cả hai định nghĩa sau của main:

int main ()

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

và tiếp tục thảo luận về các yêu cầu trên argcargv.

Vì vậy, về mặt kỹ thuật, bất kỳ chương trình nào sử dụng các tên khác nhau đều không phù hợp với tiêu chuẩn và trình biên dịch được phép từ chối nó. Tất nhiên, không có trình biên dịch nào thực sự làm như vậy. Xem chủ đề này trên comp.std.c ++ hoặc phần 3.6.1 của tiêu chuẩn dự thảo C ++ 03 này .

Điều này gần như chắc chắn chỉ là một sự giám sát đơn thuần và đã được thay đổi trong C ++ 11, thay vào đó nói rằng

Tất cả các triển khai sẽ cho phép cả hai

  • một hàm của () trả về int
  • một hàm của ( int, con trỏ tới con trỏ tới char) trả vềint

như kiểu của main(8.3.5). Ở dạng thứ hai, với mục đích giải thích, tham số hàm đầu tiên được gọi argcvà tham số hàm thứ hai được gọi argv,…


29

Chắc chắn bạn có thể đổi tên các thông số này một cách an toàn theo ý muốn

 int main(int wrzlbrnft, char* _42[]) {
 }

Tên được viết bằng cát. Chúng không có bất kỳ ảnh hưởng nào đến mã được biên dịch cuối cùng.


Điều quan trọng duy nhất là, các kiểu khai báo và định nghĩa tham số thực sự khớp với nhau.

Chữ ký của main()hàm thực chất được khai báo là

 int main(int, char*[]);

nếu bạn cần sử dụng chúng trong một triển khai thực sự, bạn sẽ cần đặt tên cho chúng. Những tên được sử dụng thực sự không liên quan như đã đề cập trước đây.


5
chỉ một số từ định danh được "viết bằng cát" như bạn đặt nó. tên chức năng chắc chắn không.
Steve Cox

1
@SteveCox "tên hàm chắc chắn không phải." Cuối cùng thì họ cũng vậy. Chỉ là những con số của hạt cát :-P ...
πάντα ῥεῖ

3
ok nhưng nghiêm túc. sau khi biên dịch, mã đối tượng vẫn có tên hàm trong đó. nếu không thì liên kết sẽ không hoạt động
Steve Cox

4
@ πάνταῥεῖ: Trừ khi bạn thực hiện nỗ lực đặc biệt để loại bỏ chúng, tên hàm sẽ vẫn còn trong tệp thực thi cuối cùng.
Nick Matteo

1
@Kundor: Sau khi liên kết trên Windows, tất cả các chức năng không đặc biệt không giữ lại những cái tên
Dani

15

Đúng. Nó an toàn, trông có vẻ kỳ lạ, nhưng nó sẽ không phá vỡ bất cứ điều gì.


7

Có, nó là an toàn để sử dụng các tên khác nhau.

Cá nhân tôi, tôi sẽ không đề xuất nó, mặc dù, vì nó là truyền thống argcargvđược biết đến rộng rãi và quen thuộc với mọi lập trình viên C khác, những người đã từng làm việc với mã của bạn. Về lâu dài, việc sử dụng những cái tên riêng, đặc biệt, khác biệt của bạn sẽ gây ra nhiều sự nhầm lẫn và / hoặc thất vọng cho người đọc hơn là nó sẽ giúp bạn tiết kiệm vì bạn thích tên của mình hơn.

"Nhập gia tùy tục."


Tuy nhiên, có một số kịch bản khá rõ ràng yêu cầu sử dụng các tên khác nhau, một kịch bản nổi tiếng là khởi tạo GLUT, glutInit(&argc, argv)nơi các đối số phải được khai báo và khởi tạo khác nhau, để không cho phép GLUT ăn hết các đối số dòng lệnh, trừ khi chúng ta muốn như vậy. SO liên kết
user3078414

@ user3078414 Ví dụ thú vị, nhưng tôi không thấy nó nói gì về những gì các biến phải được đặt tên. Theo các ví dụ trong câu hỏi khác, chúng tôi có thể dễ dàng viết int dummyargc = 1; char *dummyargv[1] = {(char*)"Something"}; glutInit(&dummyargc, dummyargv);.
Steve Summit,

Cảm ơn @ steve-Summit. Một số tài liệu API xảy ra nhầm lẫn, do đó, chuỗi này hữu ích nhất trong việc làm nổi bật argc argvquy ước đặt tên, cũng như câu trả lời đóng góp của bạn. Tôi chỉ đưa nhận xét của tôi làm ví dụ về việc tốt hơn là sử dụng bất kỳ tên nào khác nhau. Đây là liên kết SO
user3078414

5

Có, bạn có thể đổi tên chúng như bạn muốn. Chúng chỉ đơn giản là tên tham số hàm, không có gì hơn.


3

Tôi cảm thấy rằng mọi người đã bao gồm các quy tắc c ++ kỹ thuật tốt và tốt: Câu trả lời là có. Hãy gạt truyền thống sang một bên và thực tế là 1 chức năng cụ thể này là đặc biệt và mang tính biểu tượng, chứa những điểm hợp lệ để không thay đổi trên cơ sở này.

Thông thường, tôi cảm thấy triết lý của các lựa chọn hiếm khi được thảo luận và do đó tôi muốn đưa ra quan điểm về vấn đề này vì tôi cảm thấy nó quan trọng đối với lý do tại sao điều này được yêu cầu bắt đầu.

Câu hỏi này đối với tôi liên quan đến một sự lựa chọn trong việc diễn đạt tiếng Anh trong mã nói chung. Bạn dường như bị làm phiền bởi các mô tả bàn tay ngắn, đặc biệt, nếu bàn tay ngắn có văn bản trông tương tự. Tuy nhiên, trong ví dụ của bạn, việc thay đổi argn thành n_of_args chỉ hoàn thành việc thay đổi một kiểu viết tắt thành một dạng tốc ký khác mà không có giá trị thực nào thêm vào: làm rõ hoặc các thuộc tính hiển thị khác.

Từ 'số' đã được thay thế bằng chữ 'n'.

Nếu bạn đang thay đổi tên tay ngắn thông qua triết lý chống bàn tay ngắn, thì một cái gì đó như thế này có vẻ phù hợp hơn:

main (int đối số, char ** đối số)

Tôi luôn nghĩ về hai điều: Đặt tên cho mọi thứ theo tên gọi của chúng và / hoặc cách sử dụng ngụ ý của chúng. Gọi nó là một đối sốVector là thừa đối với tôi vì thuộc tính của một vectơ được ngụ ý bởi hướng kép **. Vì vậy, một cách tốt hơn cho cách tôi viết mã là: ** đối số.

Một số người nói rằng biến có tên là đối số Đối số được khai báo là một int và một Số lượng không thể âm nhưng bạn có thể có một int âm {unsigned is better}.

Một lần nữa, nó là gì và nó được sử dụng như thế nào trong cách diễn giải này. Nếu nó là một Count, thì tôi sẽ cho rằng nó sẽ không bao giờ âm. Rốt cuộc, làm thế nào bạn có thể có Số lượng là -2 quả táo. Tôi sẽ nói, bạn OWE hai quả táo. Nếu đó là một Số, thì tôi hy vọng một trường hợp tiêu cực có thể xảy ra. Đây là lý do tại sao từ bổ sung 'of' có thể quan trọng đối với bạn. Điều đó, và có lẽ là một con số được gọi bởi một bộ sưu tập ngụ ý một mặt hàng cụ thể hơn là một tài sản của chính bộ sưu tập. Tức là: đối sốNumber = 5 ngụ ý một đối số cụ thể nhưng không phải numberOfArguments.

main (đối số int maxArgumentsIndex, char **).

Điều này loại bỏ sự mơ hồ. Gọi nó là một chỉ mục sẽ loại bỏ sự mơ hồ về chữ hoa và chữ thường và cũng mô tả nó là gì và cách sử dụng nó một cách bổ sung. Nó cũng ngụ ý bằng cách diễn đạt tiếng Anh rằng max là một giá trị tuyệt đối và sẽ gây cảm giác kỳ lạ khi viết mã sửa đổi giá trị này (nó phải là const). 'đối số' có ý nghĩa ở đây vì nó là số nhiều, mô tả nó là gì và nó nên được sử dụng như thế nào. Ngay cả việc giải thích theo cách này cũng có thể nguy hiểm vì Chỉ số là -1 của Đếm / Số thứ tự. 5 đối số mang lại maxIndex là 4 !!

Bất kỳ chức năng nào khác và tôi sẽ hoàn toàn sử dụng:

Hàm void (const unsigned int maxArgumentsIndex, const char ** đối số)

Không phải tất cả các tình huống đều xứng đáng với những người mô tả tay dài. Trên thực tế, đôi khi một bàn tay ngắn sẽ dễ đọc hơn, đặc biệt, trong trường hợp viết các lớp toán học như Vec3f, Matrix, Quaternion, v.v. . float x, y, z vrs. float xComponent và những thứ tương tự.

Tôi hiểu tất cả những điều này là một sự lựa chọn phong cách, nhưng có ý thức về những lựa chọn sẽ thực sự hữu ích về lâu dài. Tôi đảm bảo các lập trình viên dày dạn kinh nghiệm sẽ cảm thấy phiền khi các mảng không được viết ở dạng số nhiều, nhưng một lần nữa, main là một dạng văn xuôi đặc biệt về sự tồn tại;)


2

Theo Tiêu chuẩn C, Có, bạn có thể đổi tên, Không có gì ảnh hưởng. Như tôi đã hiểu, trong Ngôn ngữ C, tên Từ khóa / loại / mã thông báo mặc định được xác định với mục đích / cách sử dụng, vì vậy, theo cách tương tự, nó được xác định tên

argc --> argument count

argv --> argument vector

điều này cũng có ý nghĩa về mặt sử dụng, Vì vậy, bạn có thể thay đổi thành bất kỳ tên nào mong đợi Reserved names

Trong GCC, việc thực thi chương trình bắt đầu bằng tên hàm, mainnó không phụ thuộc vào các tham số của nó.

Khi bạn viết chương trình độc lập cho bộ điều khiển vi mô, bạn không cần phải bận tâm về tên mainthay vào đó bạn có thể xác định tên của riêng bạn namevà thay đổi điểm nhập Assembly để trỏ hàm của bạn. Nó phụ thuộc vào trình biên dịch bộ điều khiển và tính khả dụng của mã nguồn bộ điều khiển được xác định trước. Tôi đã làm điều này trong bộ điều khiển Freescale dưới tên Chiến binh mã.

Lưu ý của tôi:

Tốt hơn bạn nên tuân theo các tiêu chuẩn / kiểu mã chung để làm cho mã hiển thị và dễ đọc hơn


0

Nó an toàn khi có liên quan đến trình biên dịch.

Vấn đề duy nhất mà điều này có thể gây ra là nhầm lẫn. Những người đọc mã của bạn sẽ mong đợi hai biến đó có tên chuẩn. Bạn thậm chí có thể làm điều gì đó như thế này:

int main(int foo, char ** bar)
{
    int argc;
    float argv;

Nhưng tôi không nghĩ rằng tôi cần phải nói điều này sẽ tồi tệ như thế nào.


-1

Nếu bạn không thích tên biến, tại sao không thay thế chúng bằng macro #define :

#define yourCounterName argc
#define yourVectorName  argv 

Bạn sẽ không có bất kỳ rủi ro nào và tạo ra một "giải pháp sạch".


Đó không phải là hằng số, chỉ là sự thay thế.
David Dunham
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.