2009-04-01 26 views
7

Tôi hiện đang viết C (không phải C++). Có vẻ như trình biên dịch C của Microsoft yêu cầu tất cả các biến được khai báo trên đầu của hàm.Tại sao trình biên dịch C của Microsoft lại muốn các biến ở đầu hàm?

Ví dụ, đoạn mã sau sẽ không vượt qua biên soạn:

int foo(int x) { 
    assert(x != 0); 
    int y = 2 * x; 
    return y; 
} 

Trình biên dịch báo cáo một lỗi ở dòng thứ ba, nói

error C2143: syntax error : missing ';' before 'type' 

Nếu mã được thay đổi để được như dưới nó sẽ chuyển biên soạn:

int foo(int x) { 
    int y; 
    assert(x != 0); 
    y = 2 * x; 
    return y; 
} 

Nếu tôi thay đổi tên tệp nguồn từ .c.cpp, quá trình biên dịch cũng sẽ chuyển.

Tôi nghi ngờ có một tùy chọn ở đâu đó để tắt tính nghiêm ngặt của trình biên dịch, nhưng tôi chưa tìm thấy nó. bất cứ ai có thể giúp đỡ về điều này?

Xin cảm ơn trước.

Tôi đang sử dụng cl.exe được chuyển bằng Visual Studio 2008 SP1.

Đã thêm:

Cảm ơn tất cả các bạn đã trả lời! Có vẻ như tôi phải sống ở C89 với cl.exe của Microsoft.

Trả lời

33

Dường như nó đang sử dụng tiêu chuẩn C89, yêu cầu tất cả các biến phải được khai báo trước bất kỳ mã nào. Bạn có thể khởi tạo chúng bằng các chữ, vv, nhưng không được trộn lẫn mã và các biến.

Nên có cờ trình biên dịch để bật C99 ở đâu đó, điều này sẽ giúp bạn có được hành vi mà bạn đã quen.

EDIT: Googling nhanh không có vẻ đầy hứa hẹn khi bật C99. Bạn có thể phải sống với C89 (mà không phải là xấu như vậy) hoặc tìm một trình biên dịch C tốt hơn (mà sẽ là tốt hơn).

+0

+1 .. nhưng không phải để nhắc tôi về những ngày xưa tồi tệ. –

+0

Tôi đang tìm kiếm trợ giúp của cl.exe để có tùy chọn bật các tùy chọn C99. Nhưng cho đến nay tôi không có đầu mối về nó. Yêu cầu khai báo tất cả các biến ở trên cùng có vẻ vô cùng bất tiện. Nếu tôi sử dụng gcc để biên dịch mã, nó hoạt động. Điều này có nghĩa là cl.exe không hỗ trợ chuẩn C99? – yinyueyouge

+0

Ryan: có vẻ như cl.exe KHÔNG hỗ trợ C99, điều này thật đáng kinh ngạc. Đã gần 10 năm rồi! – dwc

1

Chuẩn C89 mà bạn phải sử dụng dựa trên lỗi này, yêu cầu các biến phải được khai báo trước khi bạn bắt đầu thực hiện các câu lệnh trong bất kỳ khối nào.

Bạn sẽ không gặp phải vấn đề này với tệp mở rộng .cpp vì trình biên dịch sẽ xử lý các tệp này dưới dạng tệp C++, không có giới hạn tương tự.

Câu lệnh khẳng định của bạn là mã để bạn không thể khai báo biến sau đó (trong cùng một khối/phạm vi).

Về mặt kỹ thuật bạn có thể làm điều này:

int foo(int x) { 
    assert(x != 0); 
    { 
     int y = 2 * x; 
     return y; 
    } 
} 

nhưng tôi sẽ không khuyên nó.

+1

Hiện đại C, trái ngược với cổ xưa (Microsoft, C89) không có giới hạn này. –

2

Tôi không biết cho C99 nhưng đối với các phiên bản trước đó của các biến ngôn ngữ địa phương phải được khai báo ở đầu khối {}.

1

Trong C90, tất cả các biến phải được khai báo trước câu lệnh đầu tiên. Đây không phải là trường hợp trong C99. Tôi cho rằng bạn có thể xem trình biên dịch có chuyển đổi cho C99 hay không.

0

Thông số C yêu cầu tất cả các biến được khai báo trước dòng đầu tiên của mã thực thi. Trình biên dịch tuân thủ spec. Một số trình biên dịch được khoan dung trong lĩnh vực này.

+3

C99 đã thay đổi điều này. – Richard

1

Nó giúp dễ dàng dịch sang hội đồng. Tất cả các biến được đẩy lên ngăn xếp khi bạn nhập hàm, do đó bạn không phải lo lắng về việc thực hiện nó ở bất kỳ đâu.

+0

Nó không phải là khó khăn trong mọi trường hợp. Không có vấn đề gì khi xây dựng bảng biểu tượng trước khi tạo mã. –

+0

Biến không được "đẩy vào ngăn xếp", con trỏ ngăn xếp được sửa đổi đơn giản.Và thậm chí với việc khai báo tất cả các biến ở trên cùng của một hàm, trình tối ưu hóa có một số mất nhiều thời gian trong việc quyết định khi nào và cách phân bổ stack. – snemarch

7

Trình biên dịch C của Microsoft là C89 compilant và không được nâng cấp nữa, chuẩn C99 không được lên kế hoạch. Đối với đồng bằng C trong C99 (các biến không bắt đầu khối) sử dụng trình biên dịch khác hoặc phần mở rộng C++.

+0

Trong khi một số thay đổi C99 được thực hiện để sao chép tiêu chuẩn C++, và chuẩn C++ 0x (mà MSVC++ sẽ tuân thủ, ít nhất một phần) sẽ có một số thay đổi của C99, C++ không phải C, và nhiều hơn nữa sau tiêu chuẩn C99. –

1

Đồng ý với nhận xét về thông số C. Hãy nhớ rằng C đã được tạo ra trong một thời gian khi các máy tính không có nhiều bộ nhớ.

Một cách để giải quyết điều đó là đảm bảo rằng tệp nguồn có thể được đọc trong một lần truyền từ trên xuống dưới (cũng là lý do tại sao .h-tệp được sử dụng -> chúng cho biết mã nhất định các hàm thực sự tồn tại, nhưng có thể ở đâu đó sau lần đầu tiên chúng được tham chiếu). Có thể dễ dàng hơn để tạo trình biên dịch cho mã khai báo biến ở đầu phạm vi hơn là mã cho phép khai báo biến ở bất kỳ đâu.

3

Như những người khác đã nói, đây chỉ là phiên bản của C mà MSC hỗ trợ. Tuy nhiên, nếu bạn chuẩn bị xúc phạm những người thuần túy, bạn có thể buộc trình biên dịch biên dịch thành C++.

Điều này sẽ tạo ra rất ít sự khác biệt đối với C thuần túy (có một số quy tắc về cách tạo con trỏ void và thay đổi trang trí tên), nhưng có thể cung cấp cho bạn một kết hợp hữu ích. Mã được tạo ra sẽ giống nhau - không có mất mát (hoặc đạt được) hiệu quả phép thuật bằng cách thực hiện thay đổi này.

Bạn không nói lý do tại sao bạn muốn sử dụng C.

+2

Bạn có thể muốn đặt cờ trình biên dịch thành "C++ trừ ngoại lệ". – MSalters

1

Đó là một sự xấu hổ rằng MS không thực hiện khai báo hỗn hợp và báo cáo như một phần mở rộng cho trình biên dịch C (ngay cả khi nó tắt theo mặc định và cần được bật). Tôi không chắc chắn, nhưng tôi nghĩ rằng đó là một phần mở rộng khá phổ biến trong các trình biên dịch C-C không khác; nó có vẻ như thường đủ, tôi phải sửa chữa nguồn và mẫu để biên dịch trong MSVC.

Tôi nghĩ rằng sẽ tương đối dễ thực hiện, vì tất nhiên họ đã làm điều đó cho C++.

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