C++跨平台开发总结
C++编写的程序是可以跨平台的,这是因为C++语言本身是一种独立于平台的编程语言。但是不同的操作系统和不同的编译器使用起来会有一些差异,这里记录了C++跨Win/Linux平台开发时需要注意的一些要点。
宏隔离
系统宏
Windows系统宏
- _WIN32:在所有 Windows 平台上定义,包括 32 位和 64 位 Windows 系统。只要是 Windows 平台,都会定义这个宏。
- _WIN64:仅在 64 位 Windows 平台上定义。如果程序在 64 位 Windows 上编译,这个宏会被定义。
- WIN32:这个宏与 _WIN32 类似,用于兼容性目的,通常不推荐直接使用
Linux系统宏
- __linux__:在所有 Linux 平台上定义。表示程序是在 Linux 系统上编译的。
- __unix__:在所有类 Unix 平台上定义,包括 Linux、BSD、Mac OS X 等。表示程序是在 Unix 或类 Unix 系统上编译的。
- __gnu_linux__:特指 GNU/Linux 系统。大部分情况下与 linux 一起定义。
MAC系统宏
- __APPLE__:在 macOS 和 iOS 平台上定义。表示程序是在 Apple 操作系统上编译的。
- __MACH__:在基于 Mach 内核的操作系统上定义,包括 macOS。通常与 APPLE 一起定义,用于进一步识别 macOS。
编译器宏
GCC编译器
- __GNUC__:定义 GCC 编译器的主版本号。例如,GCC 9.x 会定义 GNUC 为 9。
- __GNUC_MINOR__:定义 GCC 编译器的次版本号。例如,GCC 9.3 会定义 GNUC_MINOR 为 3。
- __GNUC_PATCHLEVEL__:定义 GCC 编译器的修订版本号。例如,GCC 9.3.0 会定义 GNUC_PATCHLEVEL 为 0。
- __VERSION__:定义 GCC 的完整版本字符串。
Clang/LLVM编译器
- __clang__:在使用 Clang 编译器时定义。
- __clang_major__:定义 Clang 编译器的主版本号。
- __clang_minor__:定义 Clang 编译器的次版本号。
- __clang_patchlevel__:定义 Clang 编译器的修订版本号。
MSVC (Microsoft Visual C++)编译器
MSVC 是 Microsoft 的 C++ 编译器,主要用于 Windows 平台的开发。
- _MSC_VER:定义 MSVC 编译器的版本号。例如,Visual Studio 2019 的 _MSC_VER 是 1920。
- _MSC_FULL_VER:定义 MSVC 编译器的完整版本号,包含修订号。
- _MSC_BUILD:定义 MSVC 编译器的内部版本号。
架构宏
~
__i386__:在 32 位 x86 架构上定义。
__x86_64__:在 64 位 x86 架构上定义
__arm__:在 32 位 ARM 架构上定义
aarch64 或 __arm64__:在 64 位 ARM 架构上定义。
C++版本宏
__cplusplus:定义 C++ 标准的版本。不同版本的 C++ 标准有不同的值。例如,C++98 为 199711L,C++11 为 201103L,C++14 为 201402L,C++17 为 201703L,C++20 为 202002L。
文件系统
本节内容不过多展开文件系统本身,而是总结不同系统文件系统在程序开发时需要注意的事项。
大小写
由于历史原因,Win中的文件默认情况下不区分文件名的大小写,而Linux是区分大小写的。为了程序的可移植性,建议在Win系统中编程也注意区分大小写。
文件分隔符
Win平台的分隔符为双反斜杠\\
而Linux的文件分隔符为单斜杠/
。大多数API两者路径分隔符都支持,但是为了考虑兼容性,可以使用系统宏对文件分隔符做处理
1 |
专属头文件
Linux头文件
在Linux系统上,C++编程中可以用到一些特定的头文件,这些头文件通常与Linux系统特有的功能和API有关。以下是一些在Linux上才有的常见头文件:
- <unistd.h>:包含了大量POSIX标准的函数声明,如
fork
、exec
、pipe
、sleep
、getpid
、getppid
等等。 - <sys/types.h>:定义了一些数据类型,如
pid_t
、uid_t
、gid_t
等,用于系统调用和库函数。 - <sys/stat.h>:提供了获取文件状态信息的函数,如
stat
、fstat
、lstat
等。 - <fcntl.h>:定义了文件控制的函数和宏,如
open
、fcntl
等。 - <sys/socket.h>:提供了套接字编程所需的结构体和函数声明,如
socket
、bind
、listen
、accept
、connect
等。 - <netinet/in.h>:定义了Internet地址族的常量和结构体,如
sockaddr_in
、INADDR_ANY
、INADDR_LOOPBACK
等。 - <arpa/inet.h>:提供了Internet操作的函数,如
inet_pton
、inet_ntop
等。 - <sys/wait.h>:定义了等待进程变更状态的函数和宏,如
wait
、waitpid
等。 - <pthread.h>:用于POSIX线程(pthreads)编程,包含线程创建、同步等相关函数。
- <sys/mman.h>:提供了内存映射相关的函数,如
mmap
、munmap
、mprotect
等。 - <sys/resource.h>:包含资源操作的函数和宏,如
getrlimit
、setrlimit
等。 - <sys/time.h>:提供了时间获取和操作的函数,如
gettimeofday
、settimeofday
、timersub
等。 - <sys/ioctl.h>:定义了设备控制接口函数,如
ioctl
。 - <sys/ipc.h>:用于进程间通信(IPC)的头文件,包含共享内存、消息队列和信号灯的功能。
- <sys/shm.h>:提供了共享内存的函数,如
shmget
、shmat
、shmdt
、shmctl
等。 - <sys/sem.h>:提供了信号量的函数,如
semget
、semop
、semctl
等。 - <sys/msg.h>:提供了消息队列的函数,如
msgget
、msgsnd
、msgrcv
、msgctl
等。
这些头文件和它们所提供的功能在编写与操作系统交互、网络编程、多线程编程、进程间通信等方面的应用程序时非常有用。
Windows头文件
Windows上也有一些专有的头文件,主要与系统API函数有关
- <windows.h>:这是一个包含了大量Windows API函数、常量、宏和数据类型的头文件,是使用Windows API进行系统编程的基础。
- <winsock2.h>:用于Windows Sockets 2 API的头文件,提供了网络编程的功能,如创建和操作套接字。
- <ws2tcpip.h>:包含了一些Windows Sockets 2扩展功能的头文件,如IPv6支持和高级TCP/IP操作。
- <winuser.h>:包含了用户界面相关的Windows API,如窗口管理、消息处理、输入处理等。
- <winbase.h>:包含了基础系统服务的Windows API,如进程、线程、文件操作、内存管理等。
- <winnt.h>:包含了Windows NT特定的数据类型和常量,通常与系统级编程有关。
- <winsvc.h>:用于Windows服务控制的头文件,包含了创建、管理和控制Windows服务的API。
- <processthreadsapi.h>:包含了与进程和线程管理相关的API,如创建进程和线程、同步等。
- <tlhelp32.h>:提供了进程快照功能的API,可以用于列举系统中的进程和线程。
- <shlobj.h>:包含了与Shell编程相关的API,如文件操作对话框、特殊文件夹路径等。
- <commctrl.h>:包含了常见控件库的API,如树视图、列表视图、工具栏等。
- <dbghelp.h>:提供了调试帮助功能的API,如符号处理、堆栈跟踪等。
- <aclapi.h>:包含了访问控制列表(ACL)和安全描述符相关的API。
- <sddl.h>:用于安全描述符定义语言(SDDL)字符串操作的API。
- <lm.h>:包含了网络管理功能的API,如用户、组、共享资源管理等。
- <rpc.h>:用于远程过程调用(RPC)的API。
- <wincrypt.h>:包含了加密API,用于数据加密、解密、证书管理等。
- <setupapi.h>:用于安装程序和设备管理的API。
- <tchar.h>:用于处理可移植字符集的API,支持Unicode和ANSI。
其他注意事项
未定义行为的实现是由C++编译器决定的,因此要在代码中避免未定义行为。