Thật không may, trong một nền tảng chéo, môi trường trình biên dịch chéo, không có phương pháp đáng tin cậy duy nhất để làm điều này hoàn toàn vào thời gian biên dịch.
- Cả _WIN32 và _WIN64 đôi khi đều có thể không được xác định, nếu cài đặt dự án bị lỗi hoặc bị hỏng (đặc biệt là trên Visual Studio 2008 SP1).
- Một dự án có nhãn "Win32" có thể được đặt thành 64 bit, do lỗi cấu hình dự án.
- Trên Visual Studio 2008 SP1, đôi khi intellisense không làm mờ các phần chính xác của mã, theo #define hiện tại. Điều này gây khó khăn cho việc xem chính xác #define nào đang được sử dụng tại thời điểm biên dịch.
Do đó, phương pháp đáng tin cậy duy nhất là kết hợp 3 kiểm tra đơn giản :
- 1) Cài đặt thời gian biên dịch , và;
- 2) Kiểm tra thời gian chạy , và;
- 3) Kiểm tra thời gian biên dịch mạnh mẽ .
Kiểm tra đơn giản 1/3: Cài đặt thời gian biên dịch
Chọn bất kỳ phương thức nào để đặt biến #define cần thiết. Tôi đề xuất phương pháp từ @JaredPar:
// Check windows
#if _WIN32 || _WIN64
#if _WIN64
#define ENV64BIT
#else
#define ENV32BIT
#endif
#endif
// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENV64BIT
#else
#define ENV32BIT
#endif
#endif
Kiểm tra đơn giản 2/3: Kiểm tra thời gian chạy
Trong hàm main (), kiểm tra lại để xem sizeof () có ý nghĩa không:
#if defined(ENV64BIT)
if (sizeof(void*) != 8)
{
wprintf(L"ENV64BIT: Error: pointer should be 8 bytes. Exiting.");
exit(0);
}
wprintf(L"Diagnostics: we are running in 64-bit mode.\n");
#elif defined (ENV32BIT)
if (sizeof(void*) != 4)
{
wprintf(L"ENV32BIT: Error: pointer should be 4 bytes. Exiting.");
exit(0);
}
wprintf(L"Diagnostics: we are running in 32-bit mode.\n");
#else
#error "Must define either ENV32BIT or ENV64BIT".
#endif
Kiểm tra đơn giản 3/3: Kiểm tra thời gian biên dịch mạnh mẽ
Quy tắc chung là "mọi #define phải kết thúc bằng #else sẽ tạo ra lỗi".
#if defined(ENV64BIT)
// 64-bit code here.
#elif defined (ENV32BIT)
// 32-bit code here.
#else
// INCREASE ROBUSTNESS. ALWAYS THROW AN ERROR ON THE ELSE.
// - What if I made a typo and checked for ENV6BIT instead of ENV64BIT?
// - What if both ENV64BIT and ENV32BIT are not defined?
// - What if project is corrupted, and _WIN64 and _WIN32 are not defined?
// - What if I didn't include the required header file?
// - What if I checked for _WIN32 first instead of second?
// (in Windows, both are defined in 64-bit, so this will break codebase)
// - What if the code has just been ported to a different OS?
// - What if there is an unknown unknown, not mentioned in this list so far?
// I'm only human, and the mistakes above would break the *entire* codebase.
#error "Must define either ENV32BIT or ENV64BIT"
#endif
Cập nhật 2017-01-17
Nhận xét từ @AI.G
:
4 năm sau (không biết có thể trước đây không), bạn có thể chuyển đổi kiểm tra thời gian chạy sang thời gian biên dịch bằng cách sử dụng xác nhận tĩnh: static_assert (sizeof (void *) == 4);. Bây giờ tất cả đã được thực hiện vào thời gian biên dịch :)
Phụ lục A
Ngẫu nhiên, các quy tắc trên có thể được điều chỉnh để làm cho toàn bộ cơ sở mã của bạn đáng tin cậy hơn:
- Mỗi câu lệnh if () kết thúc bằng "other" tạo cảnh báo hoặc lỗi.
- Mỗi câu lệnh switch () kết thúc bằng "default:" tạo cảnh báo hoặc lỗi.
Lý do tại sao điều này hoạt động tốt là vì nó buộc bạn phải nghĩ trước mọi trường hợp riêng lẻ và không dựa vào logic (đôi khi thiếu sót) trong phần "khác" để thực thi mã chính xác.
Tôi đã sử dụng kỹ thuật này (trong số nhiều người khác) để viết một dự án 30.000 hoạt động hoàn hảo kể từ ngày nó được triển khai lần đầu tiên (đó là 12 tháng trước).