8

Tôi đang cố gắng viết một chương trình biên dịch trong Borland C++ và Visual C++. Để thực hiện việc này, tôi thêm #ifdef _MSC_VER để bao gồm tệp stdafx.h khi nguồn được biên dịch theo VS. Đoạn mã biên dịch và thực thi OK trong Borland C++, nhưng trong VS, nó không thành công:Tại sao tôi nhận được lỗi biên dịch sau khi tôi có điều kiện bao gồm stdafx.h?

lỗi C1020: #endif bất ngờ

#ifdef _MSC_VER //I'm in VS 
#include "stdafx.h" 
#endif //this line doesn't compile in VS 


#ifdef __BORLANDC__ //I'm in Borland 
#pragma hdrstop 
#pragma argsused 
#endif 

#include <iostream> 

int main(int argc, char* argv[]) 
{ 
    std::cout << "Hello" << std::endl; 
    std::cin.get(); 
    return 0; 
} 

Làm thế nào tôi có thể sửa chữa lỗi này?

Trả lời

11

Cách MSVC thực hiện tiêu đề biên dịch sẵn, về cơ bản là trình biên dịch bỏ qua tất cả mọi thứ lên đến dòng đó sẽ đem lại trong tiêu đề biên dịch sẵn, và bắt đầu lại từ đầu ở đó. Vì vậy, khi bạn biên dịch chương trình của bạn, nó không "nhớ" dòng #ifdef, do đó, dòng #endif không có ý nghĩa gì với nó.

Vấn đề là, không có gì vốn có "MS" về stdafx.h, vượt ra ngoài lược đồ đặt tên đặc biệt [mà bạn có thể thay đổi dù sao đi nữa]. Vậy tại sao bận tâm ngăn chặn việc đưa vào Borland ngay từ đầu? Kịch bản trường hợp xấu nhất, bạn di chuyển khối _MSC_VER vào tiêu đề và bạn kết thúc trong cùng một tình huống hiện tại, ngoại trừ có một tệp bao gồm lãng phí. Hoặc bạn để hệ thống xây dựng của bạn chuyển hướng #include tới tệp stdafx.h Borland cụ thể.

2

Đó phải là hiệu ứng tính năng tiêu đề được biên dịch trước. Giải pháp đơn giản là tắt nó trong cài đặt dự án VS. Vấn đề là, trình biên dịch reset trạng thái của nó khi nó gặp dòng

#include "stdafx.h" 

tình trạng lần lưu trong tập tin tiêu đề biên dịch sẵn. Vì vậy, các dòng #ifdef... trở thành ignored#endif dòng gây ra trình biên dịch lỗi

1

Người khác đã nhận xét về sự cố PCH. Trên một ghi chú riêng, ở Borland, #pragma argsused phải được đính kèm với một hàm. Mục đích của nó là để duy nhất cho trình biên dịch mà các đối số của hàm không được sử dụng bởi phần thân hàm do đó nó không phát ra các cảnh báo "đối số không được sử dụng". Do đó, bạn không thể nhóm #pragma hdrstop#pragma argsused trong cùng một khối #ifdef. Bạn cần phải tách chúng, ví dụ:

#include "stdafx.h" 

#ifdef __BORLANDC__ 
#pragma hdrstop 
#endif 

#include <iostream> 

#ifdef __BORLANDC__ 
#pragma argsused 
#endif 
int main(int argc, char* argv[]) 
{ 
    std::cout << "Hello" << std::endl; 
    std::cin.get(); 
    return 0; 
} 

Một giải pháp đơn giản hơn là chỉ đơn giản là nhận xét ra các tên tham số thay vì:

#include "stdafx.h" 

#ifdef __BORLANDC__ 
#pragma hdrstop 
#endif 

#include <iostream> 

int main(int /*argc*/, char* /*argv[]*/) 
{ 
    std::cout << "Hello" << std::endl; 
    std::cin.get(); 
    return 0; 
} 
5

Nếu chúng ta chuyển đổi trình biên dịch có điều kiện để stdafx.h chúng ta có thể tránh được lỗi này. ví dụ dòng mã sau đây có thể được định nghĩa trong stdafx.h

********************* stdafx.h ************************** 
    #pragma once 

    #if defined (_MSC_VER) 

    #include "targetver.h" 

    #define WIN32_LEAN_AND_MEAN    
    // Windows Header Files: 
    #include <windows.h> 
    #endif 
    ********************************************************* 

bạn có thể chuyển pragma once hoặc truyền thống bảo vệ đầu trong điều kiện vĩ mô này như bạn mong đợi. do đó, chúng tôi có thể xây dựng stdafx.h với bất kỳ trình biên dịch C/C++ nào kể từ khi chúng tôi khai báo câu lệnh điều kiện vĩ mô của chúng tôi intostdafx.h

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