Câm int chính (vooid)? Làm thế nào mà làm việc?


135

Gần đây tôi đã phải gõ một chương trình kiểm tra C nhỏ và trong quá trình đó, tôi đã mắc một lỗi chính tả trong chức năng chính do vô tình sử dụng vooidthay vì void.

Vậy mà nó vẫn hoạt động.

Giảm nó xuống phiên bản hoàn chỉnh nhỏ nhất của nó, tôi đã kết thúc với:

int main (vooid) {
    return 42;
}

Điều này thực sự biên dịch ( gcc -Wall -o myprog myprog.c) và khi chạy, nó trả về 42.

Làm thế nào chính xác là mã hợp lệ này?


Đây là bản cắt và dán từ bashvỏ của tôi để hiển thị những gì tôi đang làm:

pax$ cat qq.c
int main (vooid) {
    return 42;
}

pax$ rm qq ; gcc -Wall -o qq qq.c ; ./qq

pax$ echo $?
42

Bằng cách xác định chính với một inttham số duy nhất , bạn gọi Hành vi không xác định . Bất cứ điều gì cũng có thể xảy ra :)
pmg

9
Trên thực tế, tôi không chắc chắn về UB, @pmg. ISO đặc biệt cho phép các khả năng khác maintừ hai tiêu chuẩn chính. Đối với tính di động, bạn nên sử dụng một trong hai điều đó nhưng tôi không nghĩ rằng UB áp dụng ở đây.
paxdiablo

Hmm: trong môi trường lưu trữ mainphải có một trong 2 dạng chính tắc (2.1.2.2). Nhưng bạn đúng @pax, trong môi trường tự do, định danh mainkhông có gì đặc biệt: nếu được sử dụng như một hàm, nó có thể thuộc bất kỳ loại nào và có bất kỳ số lượng tham số nào.
pmg

2
Trong C99, freestanding hoàn toàn được xác định. Đối với máy chủ lưu trữ, phần 5.1.2.2.1 ở cuối "hoặc theo một số cách xác định thực hiện khác", do đó, ở mức tối thiểu, hai hình thức chính tắc cũng có thể có các dạng khác (điều này sẽ cho phép UNIXy int main (int argc, char *argv[], char *envp[]);tuân thủ ).
paxdiablo

Câu trả lời:


220

Nó chỉ đơn giản là sử dụng cú pháp khai báo hàm "kiểu cũ"; bạn đang ngầm tuyên bố một inttham số được gọi vooid.


2
Điều này dường như là trường hợp. Nếu bạn thêm "vooid = 42; return vooid;" đến chính, bạn cũng nhận được giá trị trả về là 42.
Jeff Ames

43
Aargghh, bạn đúng. Nếu tôi thêm -std=c99, tôi nhận được qq.c:1: warning: type of 'vooid' defaults to 'int'.
paxdiablo

70

Đó là mã hợp lệ, vì myprog.c chứa:

int main (vooid) // vooid is of type int, allowed, and an alias for argc
{     
  return 42; // The answer to the Ultimate Question
} 

vooidchứa một cộng với số lượng đối số được truyền (nghĩa là argc). Vì vậy, trong thực tế, tất cả những gì bạn đã làm là đổi tên argcthành vooid.


11
Nếu bạn làm "trở lại vooid;" thay vào đó, nó thực sự cho 1 + num. của các đối số.
Jeff Ames

6
@Jeff, tên của chương trình được tính là một cuộc tranh cãi, do đó, + 1
Martin Beckett

23

Trong C, loại mặc định cho một đối số chức năng là int. Vì vậy, chương trình của bạn đang xử lý từ vooidnhư int main(int vooid)là mã hoàn toàn hợp lệ.


20

Nó chỉ gcc -std=c89 -Wall -o qq qq.cgcc -std=gnu89 -Wall -o qq qq.ckhông phát ra một cảnh báo. Tất cả các tiêu chuẩn khác phát ra một cảnh báo về loại ngầm intcho vooid.

int main(chart)cư xử giống như vậy int main (vooid).

return vooid; trả về số lượng đối số dòng lệnh.

Tôi đã thử nghiệm với gcc 4.4.5 trên hệ thống thử nghiệm Debian.

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.