Xác định 32 so với 64 bit trong C ++


136

Tôi đang tìm cách để xác định một cách đáng tin cậy liệu mã C ++ có được biên dịch trong 32 so với 64 bit hay không. Chúng tôi đã đưa ra những gì chúng tôi nghĩ là một giải pháp hợp lý bằng cách sử dụng macro, nhưng tò mò muốn biết liệu mọi người có thể nghĩ về trường hợp điều này có thể thất bại hoặc nếu có cách nào tốt hơn để làm điều này. Xin lưu ý rằng chúng tôi đang cố gắng thực hiện điều này trong môi trường đa nền tảng, nhiều trình biên dịch.

#if ((ULONG_MAX) == (UINT_MAX))
# define IS32BIT
#else
# define IS64BIT
#endif

#ifdef IS64BIT
DoMy64BitOperation()
#else
DoMy32BitOperation()
#endif

Cảm ơn.


8
Nếu bạn thực sự quan tâm kích thước từ của kiến ​​trúc của bạn là gì, thì đừng bỏ qua khả năng đó không phải là 32 hay 64 bit. Có những kiến ​​trúc 16 và 128 bit ngoài kia, bạn biết đấy.
alex tingle

Sự khác biệt giữa hoạt động 64 bit và 32 bit là gì?
peterchen

2
Bạn thực sự không nên điều kiện hóa điều này trên độ rộng từ của nền tảng đích. Thay vào đó, sử dụng trực tiếp kích thước của các kiểu dữ liệu có liên quan để xác định những việc cần làm. stdint.hcó thể là bạn của bạn, hoặc bạn có thể cần phát triển một số typedefs phù hợp của riêng bạn.
Phil Miller

Thử nghiệm này dường như không hoạt động trên Visual Studio 2008 SP1. Nó bị kẹt trên "IS64BIT" cho cả 32 bit và 64 bit.
Contango

Câu trả lời:


99

Thật không may, không có macro nền tảng chéo xác định 32/64 bit trên các trình biên dịch chính. Tôi đã tìm thấy cách hiệu quả nhất để làm điều này là sau đây.

Đầu tiên tôi chọn đại diện của riêng tôi. Tôi thích ENVIRONMENT64 / ENVIRONMENT32. Sau đó, tôi tìm hiểu tất cả các trình biên dịch chính sử dụng để xác định xem đó có phải là môi trường 64 bit hay không và sử dụng điều đó để đặt các biến của tôi.

// Check windows
#if _WIN32 || _WIN64
#if _WIN64
#define ENVIRONMENT64
#else
#define ENVIRONMENT32
#endif
#endif

// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENVIRONMENT64
#else
#define ENVIRONMENT32
#endif
#endif

Một cách dễ dàng hơn là chỉ cần đặt các biến này từ dòng lệnh của trình biên dịch.


3
tốt, có tồn tại các trình biên dịch khác ngoài GCC và VS. Ví dụ: QNX và GHS xuất hiện trong tâm trí (mặc dù tôi nghi ngờ QNX có định nghĩa thời gian xây dựng tương tự như GCC). Ngoài ra, bạn đã quên các kiến ​​trúc MIPS64 và IA64 trong kiểm tra GCC của bạn
Rom

14
@Rom, chắc chắn hơn 2 trình biên dịch và kiến ​​trúc. Đây chỉ là một ví dụ về cách tiếp cận vấn đề này, không phải là một giải pháp hoàn chỉnh.
JaredPar

2
Tôi nói "thường". "Lý tưởng" có lẽ là thực tế hơn.
Steve Jessop

7
Tôi nghĩ bạn nên sử dụng "#if được xác định ( WIN32 ) || được xác định (_WIN64)", v.v.
KindDragon

3
#if _WIN32 || _WIN64... #elif __GNUC__... #else # error "Missing feature-test macro for 32/64-bit on this compiler."?
Davislor

100
template<int> void DoMyOperationHelper();

template<> void DoMyOperationHelper<4>() 
{
  // do 32-bits operations
}

template<> void DoMyOperationHelper<8>() 
{
  // do 64-bits operations
}

// helper function just to hide clumsy syntax
inline void DoMyOperation() { DoMyOperationHelper<sizeof(size_t)>(); }

int main()
{
  // appropriate function will be selected at compile time 
  DoMyOperation(); 

  return 0;
}

2
Điều gì xảy ra nếu size_t không phải là 4 hay 8?
Jesper

16
@Jesper, sau đó bạn sẽ gặp lỗi liên kết trong mẫu ở trên. Hoặc bạn có thể triển khai DoMyOperation cho trường hợp đó
Kirill V. Lyadvinsky

1
Việc sử dụng khéo léo các mẫu và kudos để kiểm tra những gì quan trọng (kích thước của một số loại cụ thể) chứ không phải là một mối tương quan.
Phil Miller

2
Cẩn thận với việc sử dụng size_t cho việc này. Ví dụ, bạn có thể gặp sự cố không tương ứng với kích thước con trỏ (ví dụ: trên các nền tảng có nhiều hơn một kích thước con trỏ).
Logan Capaldo

8
Standard nói rằng kích thước của size_tnó đủ lớn để giữ kích thước của bất kỳ đối tượng được phân bổ nào trong hệ thống. Thông thường nó là những gì bạn muốn biết trong khi biên dịch có điều kiện. Nếu đó không phải là điều bạn muốn, bạn có thể sử dụng đoạn mã này với một số loại khác thay vì size_t. Ví dụ, nó có thể void*.
Kirill V. Lyadvinsky

44

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).


sizeof(void*)nó được giải quyết tại thời gian biên dịch hoặc thời gian chạy? nếu đó là vào thời gian biên dịch thì tại thời điểm chạy, kiểm tra sẽ luôn luôn if(8!=8){...}.
Ameen

@ameen Nó được giải quyết vào thời gian chạy. Mục đích của kiểm tra này là để đảm bảo rằng chương trình thoát với một lỗi thích hợp nếu bitness không như mong đợi. Điều này có nghĩa là nhà phát triển có thể khắc phục lỗi này ngay lập tức, thay vì cố gắng chẩn đoán các lỗi tinh vi xuất hiện sau này.
Contango

3
4 năm sau (không biết có thể thực hiện được trước đó 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 :)
Al.G.

1
static_assert(sizeof(void*) * CHAR_BIT == 32)là biểu cảm và chính xác hơn về mặt kỹ thuật (mặc dù tôi không biết bất kỳ kiến ​​trúc nào trong đó các byte có số lượng bit khác nhau hơn 8)
Xeverous

1
Xem thêm câu trả lời của tôi dưới đây kết hợp câu trả lời tuyệt vời này với " Macros tốt hơn, cờ tốt hơn " từ Fluent C ++.
kim loại

30

Bạn sẽ có thể sử dụng các macro được xác định trong stdint.h. Đặc biệt INTPTR_MAXlà chính xác giá trị bạn cần.

#include <cstdint>
#if INTPTR_MAX == INT32_MAX
    #define THIS_IS_32_BIT_ENVIRONMENT
#elif INTPTR_MAX == INT64_MAX
    #define THIS_IS_64_BIT_ENVIRONMENT
#else
    #error "Environment not 32 or 64-bit."
#endif

Một số phiên bản (tất cả?) Của trình biên dịch Microsoft không đi kèm stdint.h . Không chắc chắn tại sao, vì đó là một tập tin tiêu chuẩn. Đây là phiên bản bạn có thể sử dụng:http://msinttypes.googlecode.com/svn/trunk/stdint.h


4
Tại sao không có stdint.h cho Microsoft? Bởi vì nó được giới thiệu với tiêu chuẩn C99 và Microsoft dường như có ác cảm tích cực trong việc thực hiện ngay cả những thứ dễ nhất từ ​​C99. Ngay cả những thứ thư viện dễ dàng không yêu cầu thay đổi trình biên dịch. Ngay cả những thứ đã được thực hiện khi biên dịch cho C ++ (như khai báo sau các câu lệnh). Tôi biết rằng nó cần thử nghiệm, v.v., nhưng tôi cũng biết rằng MS nhận được (hoặc đã từng có) một đoạn thư viện công bằng từ Dinkumware / Plauger, và Dinkumware đã có thư viện C99 trong nhiều năm.
Michael Burr

2
VC ++ 2010 (beta 1, dù sao) có <stdint.h><cstdint>. Đối với tình trạng hiện tại - thư viện VC ++ bắt nguồn từ Dinkumware (vẫn vậy - TR1 cũng được lấy từ đó), nhưng từ những gì tôi nhớ lại khi đọc trên VCBlog, nó đã trải qua quá trình tái cấu trúc khá quan trọng để biên dịch sạch /clr, hoạt động với tất cả MSVC các loại không chuẩn như __int64, v.v. - đó là lý do tại sao nó không đơn giản như chỉ lấy nó và đưa nó vào phiên bản trình biên dịch tiếp theo.
Pavel Minaev

2
Điều này dẫn tôi đến câu trả lời đúng, nhưng tôi nghĩ bạn nên so sánh với UINT64_MAX chứ không phải INT64_MAX. Tôi đã sử dụng SIZE_MAX == UINT64_MAX - thăm dò tương tự
Arno Duvenhage

15

Điều đó sẽ không hoạt động trên Windows để bắt đầu. Cả dài và int đều là 32 bit cho dù bạn đang biên dịch cho các cửa sổ 32 bit hay 64 bit. Tôi nghĩ rằng việc kiểm tra xem kích thước của một con trỏ là 8 byte có lẽ là một tuyến đáng tin cậy hơn.


2
Thật không may sizeof bị cấm trong #if directive (nếu bạn nghĩ về nó, bộ xử lý trước không có cách nào để nói)
EFraim

Đúng, đó là lý do tại sao tôi để nó ở chỗ đề nghị kiểm tra kích thước của một con trỏ thay vì sử dụng sizeof - Tôi không thể nghĩ ra một cách di động để làm điều đó khỏi đỉnh đầu của tôi ...
mattnewport

3
Câu hỏi không (chưa) nói nó được thực hiện tại thời gian trước khi xử lý. Nhiều / hầu hết các trình biên dịch với tối ưu hóa sẽ thực hiện tốt công việc loại bỏ mã chết, ngay cả khi bạn "để nó cho đến khi chạy" với một bài kiểm tra như thế nào sizeof(void*) == 8 ? Do64Bit() : Do32Bit();. Điều đó vẫn có thể để lại một hàm không được sử dụng trong nhị phân, nhưng biểu thức có khả năng được biên dịch chỉ để gọi một hàm "đúng".
Steve Jessop

1
@onitherone giải quyết vấn đề gọi hàm, nhưng nếu tôi muốn khai báo một biến một loại khác dựa trên nền tảng, thì điều đó cần phải được thực hiện tại bộ tiền xử lý trừ khi bạn muốn khai báo nhiều biến và sử dụng chúng dựa trên câu lệnh if ( cũng sẽ được tối ưu hóa nếu chúng không được sử dụng, nhưng sẽ không dễ chịu trong mã)
Falaina

1
Vậy thì bạn đã đúng, một biểu thức không đổi trong một điều kiện là không tốt. Cách tiếp cận của Kirill có thể làm những gì bạn muốn, mặc dù:template<int> struct Thing; template<> struct Thing<4> { typedef uint32_t type; }; template<> struct Thing<8> { typedef uint64_t type; }; typedef Thing<sizeof(void*)>::type thingtype;
Steve Jessop

9

Bạn có thể làm điều này:

#if __WORDSIZE == 64
char *size = "64bits";
#else
char *size = "32bits";
#endif

1
Trong nhiều môi trường lập trình cho các ngôn ngữ có nguồn gốc C và C trên các máy 64 bit, các biến "int" vẫn rộng 32 bit, nhưng các số nguyên và con trỏ dài rộng 64 bit. Chúng được mô tả là có mô hình dữ liệu LP64. unix.org/version2/whatsnew/lp64_wp.html
Hermes

6
Try this:
#ifdef _WIN64
// 64 bit code
#elif _WIN32
// 32 bit code
#else
   if(sizeof(void*)==4)

       // 32 bit code
   else 

       // 64 bit code   
#endif

7
Mã này không đúng. Trên 64 bit, cả _WIN32 và _WIN64 đều được xác định. Nếu bạn xoay nó (đầu tiên hãy kiểm tra _WIN64), nó hoạt động tất nhiên.
BertR

4

"Được biên dịch trong 64 bit" không được xác định rõ trong C ++.

C ++ chỉ đặt giới hạn thấp hơn cho các kích thước như int, long và void *. Không có gì đảm bảo rằng int là 64 bit ngay cả khi được biên dịch cho nền tảng 64 bit. Mô hình cho phép ví dụ 23 bit ints vàsizeof(int *) != sizeof(char *)

Có các mô hình lập trình khác nhau cho các nền tảng 64 bit.

Đặt cược tốt nhất của bạn là một thử nghiệm cụ thể nền tảng. Tốt nhất thứ hai, quyết định di động của bạn phải cụ thể hơn trong những gì 64 bit là.


3

Cách tiếp cận của bạn không quá xa vời, nhưng bạn chỉ kiểm tra xem longintcó cùng kích cỡ hay không. Về mặt lý thuyết, cả hai có thể là 64 bit, trong trường hợp đó, kiểm tra của bạn sẽ thất bại, giả sử cả hai đều là 32 bit. Đây là một kiểm tra thực sự tự kiểm tra kích thước của các loại chứ không phải kích thước tương đối của chúng:

#if ((UINT_MAX) == 0xffffffffu)
    #define INT_IS32BIT
#else
    #define INT_IS64BIT
#endif
#if ((ULONG_MAX) == 0xfffffffful)
    #define LONG_IS32BIT
#else
    #define LONG_IS64BIT
#endif

Về nguyên tắc, bạn có thể làm điều này cho bất kỳ loại nào mà bạn có macro được xác định hệ thống với giá trị tối đa.

Lưu ý rằng tiêu chuẩn yêu cầu long longphải có ít nhất 64 bit ngay cả trên các hệ thống 32 bit.


Một điều cần lưu ý, để xác định UINT_MAX và ULONG_MAX, bạn có thể muốn có #include <limits.h>một nơi nào đó trước khi #ifthử nghiệm.
Alexis Wilke

3

Mọi người đã đề xuất các phương pháp sẽ cố gắng xác định xem chương trình đang được biên dịch trong 32-bithay64-bit .

Và tôi muốn thêm rằng bạn có thể sử dụng tính năng c ++ 11 static_assert để đảm bảo rằng kiến ​​trúc là những gì bạn nghĩ ("để thư giãn").

Vì vậy, tại nơi bạn xác định các macro:

#if ...
# define IS32BIT
  static_assert(sizeof(void *) == 4, "Error: The Arch is not what I think it is")
#elif ...
# define IS64BIT
  static_assert(sizeof(void *) == 8, "Error: The Arch is not what I think it is")
#else
# error "Cannot determine the Arch"
#endif

static_assert(sizeof(void*) * CHAR_BIT == 32)là biểu cảm và chính xác hơn về mặt kỹ thuật (mặc dù tôi không biết bất kỳ kiến ​​trúc nào trong đó các byte có số lượng bit khác nhau hơn 8)
Xeverous

2

Mã dưới đây hoạt động tốt cho hầu hết các môi trường hiện tại:

  #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) &&     !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
    #define IS64BIT 1
 #else
    #define IS32BIT 1
#endif

3
Lưu ý rằng _WIN64yêu cầu bạn đã bao gồm <windows.h>. Với Visual C ++, nó tốt hơn để sử dụng được xây dựng trong định nghĩa biên dịch: _M_IX86, _M_X64, _M_ARM, _M_ARM64,, vv
Chuck Walbourn

Đối với PowerPC, tôi tin rằng bạn cần phải kiểm tra __ppc64__, __powerpc64___ARCH_PPC64. Điều đó cũng bắt AIX và các nền tảng khác.
jww

1

Nếu bạn có thể sử dụng các cấu hình dự án trong tất cả các môi trường của mình, điều đó sẽ giúp việc xác định biểu tượng 64 và 32 bit trở nên dễ dàng. Vì vậy, bạn có cấu hình dự án như thế này:

Gỡ lỗi
32 bit Phát hành
32 bit Gỡ lỗi
64 bit Phát hành 64 bit

EDIT: Đây là những cấu hình chung, không phải là cấu hình được nhắm mục tiêu. Gọi cho họ bất cứ điều gì bạn muốn.

Nếu bạn không thể làm điều đó, tôi thích ý tưởng của Jared.


Hoặc kết hợp cả hai: tự động phát hiện cấu hình trên các trình biên dịch mà bạn biết, nhưng quay lại xem #define được chỉ định trong dự án / dòng lệnh / bất cứ điều gì trên trình biên dịch không được nhận dạng.
Steve Jessop

4
Giải pháp dành riêng cho VisualStudio của bạn sẽ giúp gì cho câu hỏi đa nền tảng của OP ??
alex tingle

3
@Jon: Hừm. Họ không được hỗ trợ bất kỳ loại môi trường đa nền tảng theo định nghĩa . Trừ khi đó là định nghĩa của MS về đa nền tảng - hoạt động trên các hương vị mới hơn của Windows.
EFraim

1
@EFraim: Có, bạn có thể MỤC TIÊU 32 hoặc 64 bit bằng cách sử dụng VS, nhưng đó không phải là điều tôi đang nói. Các cấu hình dự án chung và các tên tôi gán cho chúng, hoàn toàn không liên quan gì đến nền tảng. Nếu cấu hình dự án là đặc thù của VS, thì thật đáng tiếc vì chúng rất tiện dụng.
Jon Seigel

1
Tôi nghĩ rằng đây là câu trả lời đúng. Nó đáng tin cậy hơn là cố gắng tự động phát hiện mọi thứ. Tất cả các IDE tôi từng thấy đều hỗ trợ tính năng này ở một số dạng và tôi cá là những IDE tôi chưa từng thấy cũng hỗ trợ nó. Nếu bạn sử dụng make, hoặc jam, bạn có thể đặt các biến từ dòng lệnh khi được gọi, theo cách thông thường.

1

Tôi sẽ đặt các nguồn 32 bit và 64 bit vào các tệp khác nhau và sau đó chọn các tệp nguồn thích hợp bằng hệ thống xây dựng.


2
Điều này sẽ tương tự như việc hệ thống xây dựng cung cấp cho bạn một cờ như -DBUILD_64BIT. Thông thường, một số thứ rất giống với cả 32 và 64 bit nên việc có nó trong cùng một tệp có thể khá thực tế.
Alexis Wilke

Duy trì các tập tin nguồn đôi là dễ bị lỗi. IMO thậm chí là một #if bit64 khổng lồ .. tất cả mã, cho 64 bit #else .. tất cả mã, cho 32bit #endif là tốt hơn thế. (# if line-by-line là lý tưởng trong quan điểm của tôi)
brewmanz

1

Mượn từ câu trả lời xuất sắc của Contango ở trên và kết hợp nó với " Macros tốt hơn, cờ tốt hơn " từ Fluent C ++, bạn có thể làm:

// Macro for checking bitness (safer macros borrowed from 
// https://www.fluentcpp.com/2019/05/28/better-macros-better-flags/)
#define MYPROJ_IS_BITNESS( X ) MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_##X()

// Bitness checks borrowed from https://stackoverflow.com/a/12338526/201787
#if _WIN64 || ( __GNUC__ && __x86_64__ )
#    define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_64() 1
#    define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_32() 0
#    define MYPROJ_IF_64_BIT_ELSE( x64, x86 ) (x64)
    static_assert( sizeof( void* ) == 8, "Pointer size is unexpected for this bitness" );
#elif _WIN32 || __GNUC__
#    define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_64() 0
#    define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_32() 1
#    define MYPROJ_IF_64_BIT_ELSE( x64, x86 ) (x86)
    static_assert( sizeof( void* ) == 4, "Pointer size is unexpected for this bitness" );
#else
#    error "Unknown bitness!"
#endif

Sau đó, bạn có thể sử dụng nó như:

#if MYPROJ_IS_BITNESS( 64 )
    DoMy64BitOperation()
#else
    DoMy32BitOperation()
#endif

Hoặc sử dụng thêm macro tôi đã thêm:

MYPROJ_IF_64_BIT_ELSE( DoMy64BitOperation(), DoMy32BitOperation() );

0

Tôi đang thêm câu trả lời này dưới dạng ca sử dụng và ví dụ đầy đủ cho kiểm tra thời gian chạy được mô tả trong câu trả lời khác .

Đây là cách tiếp cận mà tôi đã thực hiện để truyền đạt cho người dùng cuối cho dù chương trình được biên dịch thành 64 bit hay 32 bit (hay khác, đối với vấn đề đó):

phiên bản

#ifndef MY_VERSION
#define MY_VERSION

#include <string>

const std::string version = "0.09";
const std::string arch = (std::to_string(sizeof(void*) * 8) + "-bit");

#endif

test.cc

#include <iostream>
#include "version.h"

int main()
{
    std::cerr << "My App v" << version << " [" << arch << "]" << std::endl;
}

Biên dịch và kiểm tra

g++ -g test.cc
./a.out
My App v0.09 [64-bit]
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.