2011-12-29 37 views
33

Tôi đang viết một chương trình nền tảng chéo. Tôi muốn chương trình này chạy dưới cả Windows và Linux, vì vậy tôi có hai phân đoạn mã khác nhau cho hai nền tảng. Nếu hệ điều hành là Windows, tôi muốn đoạn mã đầu tiên chạy; nếu là Linux, thì tôi muốn đoạn mã thứ hai chạy.Phát hiện Windows hoặc Linux trong C, C++

Vì vậy, tôi đã viết mã sau, nhưng nó gặp lỗi trong khi xây dựng cả trên Windows và Linux. Tôi nên làm gì để giải quyết nó?

#ifdef __unix__     /* __unix__ is usually defined by compilers targeting Unix systems */ 

    #define OS_Windows 0 
    #include <unistd.h> 
    #include <stdlib.h> 
    #include <stdio.h> 
    #include <string.h> 

#elif defined(_WIN32) || defined(WIN32)  /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */ 

    #define OS_Windows 1 
    #include <windows.h> 
    #include <stdio.h> 
    #include <tchar.h> 
    #define DIV 1048576 
    #define WIDTH 7 

#endif 

int main(int argc, char *argv[]) 
{ 
    if(OS_Windows) 
    { 
     MEMORYSTATUSEX statex; 
     statex.dwLength = sizeof (statex); 
     GlobalMemoryStatusEx (&statex); 

     _tprintf (TEXT("There is %*ld %% of memory in use.\n"), 
        WIDTH, statex.dwMemoryLoad); 

    } 

    else if(!OS_Windows) // if OS is unix 

    { 
     char cmd[30]; 
     int flag = 0; 
     FILE *fp; 
     char line[130]; 
     int memTotal, memFree, memUsed; 

     flag=0; 
     memcpy (cmd,"\0",30); 
     sprintf(cmd,"free -t -m|grep Total"); 
     fp = popen(cmd, "r"); 
     while (fgets(line, sizeof line, fp)) 
     { 
      flag++; 
      sscanf(line,"%*s %d %d %d",&TotalMem, &TotalUsed, &TotalFree); 
     } 
     pclose(fp); 

     if(flag) 
      printf("TotalMem:%d -- TotalUsed:%d -- TotalFree:%d\n",TotalMem,TotalUsed,TotalFree); 
     else 
      printf("not found\n"); 

    } 

    return 0; 
} 
+6

Những loại lỗi? –

+2

Và lỗi là? .. – kan

+0

trên linux của nó nhận được lỗi :: âMEMORYSTATUSEXâ đã không được khai báo trong phạm vi này, â 're' không được khai báo trong phạm vi này và trong cửa sổ :: lỗi C3861: 'popen': không tìm thấy định danh ... tương tự như thế này .... whay để làm gì? – Ronin

Trả lời

35

Nó thường được thực hiện như thế này (nhiều hơn hoặc ít hơn):

#ifdef _WIN32 
#include <windows.h> 
#include <stdio.h> 
#include <tchar.h> 

#define DIV 1048576 
#define WIDTH 7 
#endif 

#ifdef linux 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#endif 


int main(int argc, char *argv[]) 
{ 
#ifdef _WIN32 
MEMORYSTATUSEX statex; 
    statex.dwLength = sizeof (statex); 
    GlobalMemoryStatusEx (&statex); 

    _tprintf (TEXT("There is %*ld %% of memory in use.\n"), 
      WIDTH, statex.dwMemoryLoad); 
#endif 

#ifdef linux 
char cmd[30]; 
int flag = 0; 
FILE *fp; 
char line[130];  
int TotalMem, TotalFree, TotalUsed; 

flag=0; 
memcpy (cmd,"\0",30); 
sprintf(cmd,"free -t -m|grep Total");   
fp = popen(cmd, "r");  
while (fgets(line, sizeof line, fp)) 
{ 
    flag++; 
    sscanf(line,"%*s %d %d %d",&TotalMem, &TotalUsed, &TotalFree); 
} 
pclose(fp); 

if(flag) 
    printf("TotalMem:%d -- TotalUsed:%d -- TotalFree:%d\n",TotalMem,TotalUsed,TotalFree); 
else 
    printf("not found\n"); 
#endif 

    return 0; 
} 

Bằng cách này, chỉ mã cho Linux sẽ được biên dịch trong khi trên nền tảng Linux và chỉ có mã cửa sổ mới được biên dịch trên nền tảng Windows.

+2

thankzzz .... u r một cuộc sống tiết kiệm. – Ronin

+0

@Cicada để biên dịch mã này thay đổi int memTotal, memFree, memUsed; để int TotalMem, TotalFree, TotalUsed; –

16

Bạn nên sử dụng cùng một #ifdef thay vì if(OS_Windows) logic trong mã của bạn:

#ifdef __unix__   
... 
#elif defined(_WIN32) || defined(WIN32) 

#define OS_Windows 

#endif 

int main(int argc, char *argv[]) 
{ 
#ifdef OS_Windows 
/* Windows code */ 
#else 
/* GNU/Linux code */ 
#endif  
} 
6

Bạn đang gây nhầm lẫn các biến (tồn tại trong thời gian chạy) với các ký hiệu tiền xử lý (chỉ tồn tại trong quá trình biên dịch).

Sau khi bạn làm điều gì đó như #define OS_Windows 1, bạn không thể sử dụng OS_Windows biểu tượng như là một biến và đặt nó bên trong if() s ... Ý tôi là, bạn có thể, nhưng nó sẽ được mở rộng trong biên soạn để if (1).

Đối với một dự án cross-platform, bạn phải sử dụng #if hoặc #ifdef để đảm bảo rằng trình biên dịch chọn một phần đúng của mã cho một hệ điều hành nhất định và duy nhất mà biên dịch.

Cái gì như:

void openWindow() { 
#if OS_Windows 
    // windows-specific code goes here 
#else 
    // linux-specific code 
#endif 
} 
+0

>> "_it sẽ được mở rộng trong quá trình biên dịch thành' if (1) '_" Có, hoặc 'if (0)' nếu 'OS_Windows' được định nghĩa là 0. Câu hỏi _main_ là tại sao trì hoãn phân nhánh này để chạy thời gian, nếu chúng ta trong thời gian biên dịch đã biết, nhánh nào chúng ta cần. Vì vậy, bằng '# if'-cấu trúc, chúng ta có thể tránh thêm thời gian chạy và mã phụ – user1234567

2

chiến lược cơ bản của bạn là vô cùng thiếu sót.

Bằng cách sử dụng nếu trong hàm chính bạn đang chọn đoạn mã nào sẽ chạy lúc RUNTIME. Vì vậy, ngay cả khi biên dịch cho unix trình biên dịch vẫn phải xây dựng mã cho các cửa sổ (mà nó không làm vì các tập tin tiêu đề không được bao gồm) và ngược lại.

Bạn thay vào đó yêu cầu #if sẽ được đánh giá vào thời gian biên dịch và sẽ không cố gắng biên dịch mã không liên quan. Vì vậy, về bản chất bạn cần phải hiểu rằng nếu đánh giá định nghĩa của bạn như là một biểu thức tại thời gian chạy trong khi #if đánh giá giá trị của hằng số được xác định trước tại thời gian biên dịch.

+1

Bất kỳ trình biên dịch tối ưu nào có giá trị muối của nó sẽ loại bỏ một khối' if (0) '. – Dave

+1

@Dave Thật không may là không thực sự giúp đỡ bởi vì trình biên dịch không thể tối ưu hóa bất cứ điều gì nó sẽ không biên dịch để bắt đầu với – Elemental

+0

Điều tôi ngụ ý là vấn đề không phải là các biểu tượng không liên quan; nó không tồn tại. – Dave

5

Tôi thấy rất nhiều giải pháp khác nhau ở đây, điều này khiến tôi không thoải mái ... Điều gì sẽ xảy ra nếu chúng hoạt động trên Linux chứ không phải Windows hoặc Windows nhưng không phải Linux? Nếu họ chỉ làm việc trên một số trình biên dịch thì sao? Vv

Vì vậy, tôi tìm thấy liên kết này, mà tôi thích: http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system

Dường như đây là tốt nhất (sử dụng #ifdef, #endif vv):

  • _WIN32 cho Windows 32 bit
  • _WIN64 cho Windows 64 bit
  • __unix__ cho Unix
Các vấn đề liên quan