一、一个让我困惑很久的问题刚学 Java / Android 时我一直觉得class Dog { void run(){} }这种写法很自然。因为数据和行为放在一起有封装有继承有多态这就是标准 OOP面向对象。但后来开始接触Linux驱动JNIAndroid HALC/C我突然发现系统层代码里根本没有 class。取而代之的是struct xxx void (*xxx)(void)甚至大量代码长这样device-ops-open();我当时特别懵“这不是 C 语言吗”“怎么写得像 Java/C 一样”后来才真正理解本质上C 语言虽然没有 OOP 语法但完全可以实现 OOP 思想。而 Linux / Android 系统层本质上就是“用 C 写面向对象”。二、C 为什么需要“面向对象”C 本身是过程式语言。它没有classprivateinheritancevirtualinterface但问题是大型系统一定需要能力为什么需要封装隐藏实现细节多态统一接口继承代码复用抽象降低耦合否则驱动会乱模块无法扩展系统无法维护所以工程师开始自己“模拟 OOP”。核心思想就是struct 管状态函数管行为函数指针做动态分发于是 C 开始“长得像 C”。三、C语言如何实现 OOP 三件套1. struct 对象封装Javaclass Led { int pin; void on(){} }Ctypedef struct { int pin; } Led; void led_on(Led* led);这里JavaC类struct对象成员struct字段成员方法普通函数进一步很多工程里会这样led.htypedef struct Led Led; void led_on(Led* led);led.cstruct Led { int pin; };这叫不完整类型Opaque Pointer作用外部看不到成员只能通过接口操作这其实就是C 版 private。四、函数指针 多态最核心普通写法if(type LED_RED){ red_on(); }else{ blue_on(); }问题if/switch 巨多难扩展耦合严重于是C 引入函数指针。函数指针写法定义操作表typedef struct { void (*on)(void); void (*off)(void); } LedOps;不同对象绑定不同实现LedOps red_ops { .on red_on, .off red_off }; LedOps blue_ops { .on blue_on, .off blue_off };调用led-ops-on();看到这里是不是很眼熟因为这其实就是 C 虚函数底层思想。本质对象 ↓ 函数表(vtable) ↓ 具体实现函数也就是 “运行时动态分发”这就是C 语言的多态。五、struct嵌套 继承Javaclass Animal {} class Dog extends Animal {}C 没有 extends。于是typedef struct { int id; } Animal;子类typedef struct { Animal base; int age; } Dog;因为 struct 内存连续。所以Dog Animal 扩展字段于是Animal* a (Animal*)dog;可以成立。这就是C 语言版继承。六、整个 Linux / Android 的底层世界1. Linux 内核经典struct file_operations里面全是函数指针int (*open)(struct inode*, struct file*); int (*read)(struct file*, char*, size_t);本质“驱动多态”不同驱动open 不同read 不同write 不同但调用接口统一。2. Android HALAndroid 硬件抽象层hw_module_t本质也是struct function pointer不同厂商摄像头不同蓝牙不同GPS不同但 Framework 调用统一。3. JNI经典代码(*env)-CallVoidMethod()很多人第一次看到都懵。其实JNIEnv 本质就是函数表。也就是说JNIEnv C语言版虚函数表JNI 本质就是“C 的多态接口”。七、为什么系统层特别喜欢这种写法1. 内存完全可控没有hidden objectRTTIGC编译器隐藏逻辑系统级开发非常重要。2. ABI 稳定C ABI 是跨平台事实标准。所以Linux 内核驱动HALOpenGLFFmpeg都大量使用 C 接口。3. 性能稳定函数表调用成本明确内存布局固定无额外对象模型特别适合驱动RTOSKernel4. 更适合底层系统层最怕编译器偷偷帮你做了什么而 C 一切都摆在明面上。八、一句话总结struct 管状态函数管行为函数指针做多态struct嵌套做继承这就是C语言实现面向对象的核心思想。九、扩展这篇其实只是《C语言对象模型》系列总纲。后面准备继续深入几个系统层核心主题。第一篇世界观篇《为什么 Linux / Android 系统里全是 struct 函数指针》也就是本文。核心目标建立 C 的对象模型认知理解系统层为什么大量使用 struct 函数指针建立 Linux / Android / HAL / JNI 的统一认知第二篇多态篇《从函数指针到虚函数表彻底理解 C 的多态》这一篇会深入callbackfunction pointervtabledispatchruntime polymorphism以及device-ops-open();背后到底发生了什么。同时还会对比Java 多态C virtualC 函数表彻底讲透“虚函数表”的本质。第三篇JNI篇《JNIEnv 为什么是二级指针本质就是函数表》很多 Android 开发第一次看到(*env)-CallVoidMethod()都会懵。这一篇会彻底讲透为什么 JNI 是二级指针为什么 JNIEnv 像对象为什么 JNI 本质是函数表Java 和 Native 是如何互相调用的最终真正理解JNI 本质就是 C 风格 OOP。第四篇内核篇《Linux 内核里的 container_of 到底是什么黑魔法》这一篇会进入 Linux 内核核心技巧。深入offsetofcontainer_ofstruct embeddingintrusive list面向对象内核设计你会发现Linux 内核其实是“C语言对象模型”的终极形态。十、最后当你真正理解struct function pointer之后发现LinuxAndroid FrameworkHALJNIDriver这些系统级代码虽然写的是 C但背后其实全是“面向对象的思想”。