[转]C与跨平台开发 - 图1

在众多高级编程语言中,C 语言历史悠久,且生命力旺盛,系统开发和应用开发兼具,是信息技术发展的一把利器。这里简单介绍一下 C 语言的发展及其对跨平台开发的影响。

C语言

C 语言是在 1969 到 1973 年间,由贝尔实验室的 Dennis Ritchie 最初为重写 unix 操作系统而开发的,它成功替代了汇编语言开发操作系统的模式,随后得到了广泛飞速的发展。由于几大流行操作系统的内核(Linux、Windows 等)都是由 C 开发的,所以称之为系统编程语言,其能力不局限于系统开发。常见的高级编程语言或脚本语言,像 Java、Python、Perl 和 PHP 等都是应用类编程语言,对开发人员来说,由这些语言编写的代码,不存在运行平台的问题,很多高级语言也是由 C 来编写的。

而与众多流行的高级编程语言相比,C 语言是一种与平台真正相关的编程语言(C++ 可以认为是 C 的超集)。编译工具将 C 源代码翻译成某种机器指令集的二进制程序,这种程序只能在相应的操作系统和硬件平台上运行。Java 程序则仅需一次编译,就可到处运行,与具体的硬件平台无关,唯一条件就是该平台上得有 java 虚拟机。

跨平台开发

跨平台开发,是指一套代码(或者一种业务)在多个平台上运行的编程方式,也是一种开发技巧。平台就是业务运行的环境,Windows、Linux 和 Unix 等就是最典型的计算机操作系统平台,还有像浏览器 IE、Chrome 和 Firefox 等是一类应用平台;这些 “平台” 也有自己的运行 “平台”,Windows 可以运行在 x86、amd64 和 arm 等硬件平台上,Linux 可以跑的更多;这里讨论的平台指操作系统,涉及的平台分 Windows 和 Unix-like。各种 Unix 和各种 Linux 视为同宗,Portable Operating System Interface (POSIX) 这套规范在 Unix-like 上表现的较为一致,Windows 上也有支持,但其上的 Win32 API 功能更为丰富。

[转]C与跨平台开发 - 图2

跨平台开发当然是为了满足业务发展的需要而进行的,当你的软件在 Windows 上已运行良好,但随 Linux 市场的兴起,你不得不开发 Linux 上的产品,在 Linux 平台上重造一个 “轮子”,业务与 Windows 上运行的软件没有差异,只是换了个平台而已。由于平台的差异,操作系统提供的接口不同,开发人员根据不同的系统调用实现相同的业务需求。在开发过程中,自然而然地出现一种抽象层,将业务和运行平台进行分离。

像 Java 这样的高级语言可以算是高级抽象,使用这些应用类语言来编写软件不用考虑平台,只需关注业务,这是一种比较常用的开发模式。这样似乎没有必要使用 C 来做应用开发,但在实践当中,许许多多的基础部件:数据库 MySql、WEB 服务器 Apache 等都是 C 来开发的,因为 C 开发的软件开销少、运行效率高。

跨平台问题

C 语言本应该是跨平台的,几乎每个平台都原生支持 C 开发环境。由于 C 编译器实现的差异性和操作系统的多样性,导致用 C 开发应用时存在跨平台运行问题。

有必要说一下 C 语言的几个主要标准的进化

  • K&R C
    经典 C,事实标准,许多编译器的最低标准要求
  • C89
    标准 C,大部分 C 代码都是 C89 兼容的
  • C99
    引入了非常多的新特性,有较多的 c 编译器提供支持,gcc 就支持的很好,但微软公司对这个标准不那么热心,其集成开发工具 Visual Studio 2013 才开始比较良好地支持 C99 特性,这也成了软件从 Linux 系统移植到 Windows 平台的一个障碍。

新特性有:

  • 宏定义支持取可变参数 #define Macro(…) _VAARGS
  • 使用宏定义时,允许省略参数,被省略的参数会被扩展成空串
  • 增加了内联函数
  • 支持不定长的数组,即数组长度可以在运行时决定,比如利用变量作为数组长度。声明时使用 int a[var] 的形式。
  • 变量声明不必放在语句块的开头,随用随定义;for 语句常写成 for(int i=0;i<100;++i) 的形式,即 i 只在 for 语句块内部有效;微软的一些编译器不支持这样的书写方式。
  • 允许在 struct 的最后定义的数组不指定其长度,写做 type name[] 的形式,主要用在不定长结构体的定义中,这个特性在应用中较为常见;

结构定义

  1. struct vectord {
  2. size_t len;
  3. double arr[];
  4. };

这样使用

  1. struct vectord *vector = sizeof(struct vectord) + array_len*sizeof(double);
  2. vector->len = ...;
  3. for (int i = 0; i < vector->len; i++)
  4. vector[i] = ...
  • 初始化结构的时候允许对特定的元素赋值,形式为:
    (微软的一些编译器同样不支持。)
  1. struct test{int a[3],b;} foo[] = { [0].a = {1}, [1].a = 2 };
  2. struct test{int a, b, c, d;} foo = { .a = 1, .c = 3, 4, .b = 5 };
  • 其他标准
    C11 等,如果是跨平台开发,似乎可以无视最近标准引入的新特性了。

我们在用 C 进行开发时,尽量使用 C89 标准和部分 C99 特性,在需要依赖操作系统平台特性时,通过宏来控制相应平台上的特殊代码——

  1. #if defined(_WIN32)
  2. #define WIN32_LEAN_AND_MEAN
  3. #include <windows.h>
  4. #else
  5. #include <unistd.h>
  6. #if defined(unix)
  7. #include <sys/param.h>
  8. #endif
  9. #endif
  10. #if defined(_WIN32)
  11. #elif defined(_AIX)
  12. #include <fcntl.h>
  13. #include <sys/procfs.h> ...
  14. #elif defined(linux) ...
  15. #elif defined(__sun) && defined(__SVR4)...
  16. #endif

宏定义是 C 语言的一个特色,功能很多;可以利用它针对特定平台编译特定代码,其他平台的代码不会编译连接到执行文件中,这样产生的程序规模就会小很多,同时产生了平台依赖。而 java 程序,如果要执行特定平台的业务,需要在运行时来检查当前运行的环境,再来做出选择。

当然,我们是站在巨人肩膀上进行软件开发的,不用亲自实现每项功能,在开源世界里有许许多多通用的、成熟的工具库可以使用。

  • NSPR (NetScape Portable Runtime)
    它为非 GUI(图形界面) 开发提供了一套平台独立的系统工具库,涉及的内容包括:
    NSPR 的目标是在各个操作系统环境提供统一的 API,它不是努力输出各个操作系统的最广泛特性,而是提供最优解或者说是最佳实践,这些功能是现代操作系统的共有特性。如果出现新的操作系统,将 NSPR 移植到新平台的成功率是非常高的,主流系统 NSPR 均有支持。浏览器 Firfox 就用到了它。
    该库虽历史悠久,但生命力强盛。接口设计的比较稳定,具有很好的二进制兼容性。
    • 线程
    • 线程同步
    • 文件和网络 IO
    • 时间
    • 内存管理
    • 共享库处理
  • APR(Apache Portable Runtime)
    Apache 的跨平台库,除了基本的操作系统抽象外,还提供了比较丰富的工具。
  • OpenSSL
    网络安全通讯库
  • libcurl
    客户端网络通信开发库,支持非常多的网络协议,HTTP(S)、FTP(S)、POP3、SCP 和 SMTP 等等。

很多工具库首先以 C(或 C++) 的形式出现,然后再为其他高级语言提供功能扩展。

跨平台开发,除了语言层面上的,还有编译工具链的问题,涉及如何建立工程文件,使用什么编译器等等。CMake 系统可以帮助解决跨平台工程文件构建问题,先为平台生成对应开发环境的工程文件,再由平台上的编译工具进行编译;为可以生成 visual studio 工程文件,也可以为 Unix-like 系统生成 Makefile。

小结

C 语言既可进行操作系统开发,也可进行应用开发,适用范围广泛,对 C 开发人员来说,想象力限制了开发能力。但它不是马斯洛大锤,所要解决的问题也不都是钉子。在实践中,需要在软件运行速度和开发效率等问题上取得平衡。(徐品华 | 天存信息)

Ref

  1. C (programming language)#ANSI_C_and_ISO_C)
  2. Flexible array member
  3. Mozilla-About_NSPR
  4. CMake
    https://www.cnblogs.com/tcxa/p/14813473.html