侵权投诉

为什么要用C语言实现面向对象呢

硬件攻城狮 2021-06-04 17:44 次阅读

不知道有多少人去了解过语言的发展史,早期C语言的语法功能其实比较简单。随着应用需求和场景的变化,C语言的语法功能在不断升级变化。

虽然我们的教材有这么一个结论:C++语言是面向过程的语言,C++是面向对象的编程语言,但面向对象的概念是在C语言阶段就有了,而且应用到了很多地方,比如某些操作系统内核、通信协议等。

面向对象编程,也就是大家说的OOP(Object Oriented Programming)并不是一种特定的语言或者工具,它只是一种设计方法、设计思想,它表现出来的三个最基本的特性就是封装、继承与多态。

为什么要用C语言实现面向对象

阅读文本之前肯定有读者会问这样的问题:我们有C++面向对象的语言,为什么还要用C语言实现面向对象呢?

C语言这种非面向对象的语言,同样也可以使用面向对象的思路来编写程序的。只是用面向对象的C++语言来实现面向对象编程会更简单一些,但是C语言的高效性是其他面向对象编程语言无法比拟的。

当然使用C语言来实现面向对象的开发相对不容易理解,这就是为什么大多数人学过C语言却看不懂Linux内核源码。

所以这个问题其实很好理解,只要有一定C语言编程经验的读者都应该能明白:面向过程的C语言和面向对象的C++语言相比,代码运行效率、代码量都有很大差异。在性能不是很好、资源不是很多的MCU中使用C语言面向对象编程就显得尤为重要。

具备条件

要想使用C语言实现面向对象,首先需要具备一些基础知识。比如:(C语言中的)结构体、函数、指针,以及函数指针等,(C++中的)基类、派生、多态、继承等。

首先,不仅仅是了解这些基础知识,而是有一定的编程经验,因为上面说了“面向对象是一种设计方法、设计思想”,如果只是停留在字面意思的理解,没有这种设计思想肯定不行。

因此,不建议初学者使用C语言实现面向对象,特别是在真正项目中。建议把基本功练好,再使用。

利用C语言实现面向对象的方法很多,下面就来描述最基本的封装、继承和多态。

封装

封装就是把数据和函数打包到一个类里面,其实大部分C语言编程者都已近接触过了。

C 标准库中的 fopen(), fclose(), fread(), fwrite()等函数的操作对象就是 FILE。数据内容就是 FILE,数据的读写操作就是 fread()、fwrite(),fopen() 类比于构造函数,fclose() 就是析构函数。

这个看起来似乎很好理解,那下面我们实现一下基本的封装特性。

#ifndef SHAPE_H#define SHAPE_H #include 《stdint.h》 // Shape 的属性typedef struct {int16_t x; int16_t y; } Shape; // Shape 的操作函数,接口函数void Shape_ctor(Shape * const me, int16_t x, int16_t y);void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy);int16_t Shape_getX(Shape const * const me);int16_t Shape_getY(Shape const * const me); #endif /* SHAPE_H */

这是 Shape 类的声明,非常简单,很好理解。一般会把声明放到头文件里面 “Shape.h”。来看下 Shape 类相关的定义,当然是在 “Shape.c” 里面。

#include “shape.h” // 构造函数void Shape_ctor(Shape * const me, int16_t x, int16_t y){ me-》x = x; me-》y = y;} void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy){ me-》x += dx; me-》y += dy;} // 获取属性值函数int16_t Shape_getX(Shape const * const me) {return me-》x;}int16_t Shape_getY(Shape const * const me) {return me-》y;} 再看下 main.c

#include “shape.h” /* Shape class interface */#include 《stdio.h》 /* for printf() */ int main() { Shape s1, s2; /* multiple instances of Shape */ Shape_ctor(&s1, 0, 1); Shape_ctor(&s2, -1, 2); printf(“Shape s1(x=%d,y=%d) ”, Shape_getX(&s1), Shape_getY(&s1));printf(“Shape s2(x=%d,y=%d) ”, Shape_getX(&s2), Shape_getY(&s2)); Shape_moveBy(&s1, 2, -4); Shape_moveBy(&s2, 1, -2); printf(“Shape s1(x=%d,y=%d) ”, Shape_getX(&s1), Shape_getY(&s1));printf(“Shape s2(x=%d,y=%d) ”, Shape_getX(&s2), Shape_getY(&s2)); return 0;} 编译之后,看看执行结果:

Shape s1(x=0,y=1)Shape s2(x=-1,y=2)Shape s1(x=2,y=-3)Shape s2(x=0,y=0)

整个例子,非常简单,非常好理解。以后写代码时候,要多去想想标准库的文件IO操作,这样也有意识的去培养面向对象编程的思维。

继承

继承就是基于现有的一个类去定义一个新类,这样有助于重用代码,更好的组织代码。在 C 语言里面,去实现单继承也非常简单,只要把基类放到继承类的第一个数据成员的位置就行了。

例如,我们现在要创建一个 Rectangle 类,我们只要继承 Shape 类已经存在的属性和操作,再添加不同于 Shape 的属性和操作到 Rectangle 中。

下面是 Rectangle 的声明与定义:

#ifndef RECT_H#define RECT_H #include “shape.h” // 基类接口 // 矩形的属性typedef struct { Shape super; // 继承 Shape // 自己的属性uint16_t width;uint16_t height;} Rectangle; // 构造函数void Rectangle_ctor(Rectangle * const me, int16_t x, int16_t y,uint16_t width, uint16_t height); #endif /* RECT_H */

#include “rect.h” // 构造函数void Rectangle_ctor(Rectangle * const me, int16_t x, int16_t y,uint16_t width, uint16_t height){/* first call superclass’ ctor */ Shape_ctor(&me-》super, x, y); /* next, you initialize the attributes added by this subclass.。。 */ me-》width = width; me-》height = height;}

我们来看一下 Rectangle 的继承关系和内存布局:

50e6f2cc-c510-11eb-9e57-12bb97331649.png

因为有这样的内存布局,所以你可以很安全的传一个指向 Rectangle 对象的指针到一个期望传入 Shape 对象的指针的函数中,就是一个函数的参数是 “Shape *”,你可以传入 “Rectangle *”,并且这是非常安全的。这样的话,基类的所有属性和方法都可以被继承类继承!

#include “rect.h” #include 《stdio.h》 int main() { Rectangle r1, r2; // 实例化对象 Rectangle_ctor(&r1, 0, 2, 10, 15); Rectangle_ctor(&r2, -1, 3, 5, 8); printf(“Rect r1(x=%d,y=%d,width=%d,height=%d) ”, Shape_getX(&r1.super), Shape_getY(&r1.super), r1.width, r1.height);printf(“Rect r2(x=%d,y=%d,width=%d,height=%d) ”, Shape_getX(&r2.super), Shape_getY(&r2.super), r2.width, r2.height); // 注意,这里有两种方式,一是强转类型,二是直接使用成员地址 Shape_moveBy((Shape *)&r1, -2, 3); Shape_moveBy(&r2.super, 2, -1); printf(“Rect r1(x=%d,y=%d,width=%d,height=%d) ”, Shape_getX(&r1.super), Shape_getY(&r1.super), r1.width, r1.height);printf(“Rect r2(x=%d,y=%d,width=%d,height=%d) ”, Shape_getX(&r2.super), Shape_getY(&r2.super), r2.width, r2.height); return 0;}

输出结果:

Rect r1(x=0,y=2,width=10,height=15)Rect r2(x=-1,y=3,width=5,height=8)Rect r1(x=-2,y=5,width=10,height=15)Rect r2(x=1,y=2,width=5,height=8) 多态

C++ 语言实现多态就是使用虚函数。在 C 语言里面,也可以实现多态。 现在,我们又要增加一个圆形,并且在 Shape 要扩展功能,我们要增加 area() 和 draw() 函数。但是 Shape 相当于抽象类,不知道怎么去计算自己的面积,更不知道怎么去画出来自己。而且,矩形和圆形的面积计算方式和几何图像也是不一样的。 下面让我们重新声明一下 Shape 类:

#ifndef SHAPE_H#define SHAPE_H #include 《stdint.h》 struct ShapeVtbl;// Shape 的属性typedef struct {struct ShapeVtbl const *vptr;int16_t x; int16_t y; } Shape; // Shape 的虚表struct ShapeVtbl {uint32_t (*area)(Shape const * const me);void (*draw)(Shape const * const me);}; // Shape 的操作函数,接口函数void Shape_ctor(Shape * const me, int16_t x, int16_t y);void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy);int16_t Shape_getX(Shape const * const me);int16_t Shape_getY(Shape const * const me);

static inline uint32_t Shape_area(Shape const * const me){return (*me-》vptr-》area)(me);} static inline void Shape_draw(Shape const * const me){ (*me-》vptr-》draw)(me);} Shape const *largestShape(Shape const *shapes[], uint32_t nShapes);void drawAllShapes(Shape const *shapes[], uint32_t nShapes); #endif /* SHAPE_H */

看下加上虚函数之后的类关系图:

50fe1d08-c510-11eb-9e57-12bb97331649.png

5.1 虚表和虚指针虚表(Virtual Table)是这个类所有虚函数的函数指针的集合。 虚指针(Virtual Pointer)是一个指向虚表的指针。这个虚指针必须存在于每个对象实例中,会被所有子类继承。 在《Inside The C++ Object Model》的第一章内容中,有这些介绍。 5.2 在构造函数中设置vptr在每一个对象实例中,vptr 必须被初始化指向其 vtbl。最好的初始化位置就是在类的构造函数中。事实上,在构造函数中,C++ 编译器隐式的创建了一个初始化的vptr。在 C 语言里面, 我们必须显示的初始化vptr。 下面就展示一下,在 Shape 的构造函数里面,如何去初始化这个 vptr。

#include “shape.h”#include 《assert.h》 // Shape 的虚函数static uint32_t Shape_area_(Shape const * const me);static void Shape_draw_(Shape const * const me); // 构造函数void Shape_ctor(Shape * const me, int16_t x, int16_t y){// Shape 类的虚表static struct ShapeVtbl const vtbl = { &Shape_area_, &Shape_draw_ }; me-》vptr = &vtbl; me-》x = x; me-》y = y;} void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy){ me-》x += dx; me-》y += dy;} int16_t Shape_getX(Shape const * const me) {return me-》x;}int16_t Shape_getY(Shape const * const me) {return me-》y;} // Shape 类的虚函数实现static uint32_t Shape_area_(Shape const * const me){ assert(0); // 类似纯虚函数return 0U; // 避免警告} static void Shape_draw_(Shape const * const me){ assert(0);

// 纯虚函数不能被调用} Shape const *largestShape(Shape const *shapes[], uint32_t nShapes){ Shape const *s = (Shape *)0;uint32_t max = 0U;uint32_t i;for (i = 0U; i 《 nShapes; ++i) {uint32_t area = Shape_area(shapes[i]);// 虚函数调用if (area 》 max) { max = area; s = shapes[i]; } }return s;} void drawAllShapes(Shape const *shapes[], uint32_t nShapes){uint32_t i;for (i = 0U; i 《 nShapes; ++i) { Shape_draw(shapes[i]); // 虚函数调用 }} 5.3 继承 vtbl 和 重载 vptr上面已经提到过,基类包含 vptr,子类会自动继承。但是,vptr 需要被子类的虚表重新赋值。并且,这也必须发生在子类的构造函数中。下面是 Rectangle 的构造函数。

#include “rect.h”#include 《stdio.h》 // Rectangle 虚函数static uint32_t Rectangle_area_(Shape const * const me);static void Rectangle_draw_(Shape const * const me); // 构造函数void Rectangle_ctor(Rectangle * const me, int16_t x, int16_t y,uint16_t width, uint16_t height){static struct ShapeVtbl const vtbl = { &Rectangle_area_, &Rectangle_draw_ }; Shape_ctor(&me-》super, x, y); // 调用基类的构造函数 me-》super.vptr = &vtbl; // 重载 vptr me-》width = width; me-》height = height;} // Rectangle‘s 虚函数实现static uint32_t Rectangle_area_(Shape const * const me){ Rectangle const * const me_ = (Rectangle const *)me;

//显示的转换return (uint32_t)me_-》width * (uint32_t)me_-》height;} static void Rectangle_draw_(Shape const * const me){ Rectangle const * const me_ = (Rectangle const *)me; //显示的转换printf(“Rectangle_draw_(x=%d,y=%d,width=%d,height=%d) ”, Shape_getX(me), Shape_getY(me), me_-》width, me_-》height);}

5.4 虚函数调用有了前面虚表(Virtual Tables)和虚指针(Virtual Pointers)的基础实现,虚拟调用(后期绑定)就可以用下面代码实现了。

uint32_t Shape_area(Shape const * const me){return (*me-》vptr-》area)(me);} 这个函数可以放到.c文件里面,但是会带来一个缺点就是每个虚拟调用都有额外的调用开销。为了避免这个缺点,如果编译器支持内联函数(C99)。我们可以把定义放到头文件里面,类似下面:

static inline uint32_t Shape_area(Shape const * const me){return (*me-》vptr-》area)(me);} 如果是老一点的编译器(C89),我们可以用宏函数来实现,类似下面这样:

#define Shape_area(me_) ((*(me_)-》vptr-》area)((me_))) 看一下例子中的调用机制:

511cfe08-c510-11eb-9e57-12bb97331649.png

5.5 main.c

#include “rect.h”#include “circle.h”#include 《stdio.h》 int main(){ Rectangle r1, r2; Circle c1, c2; Shape const *shapes[] = { &c1.super, &r2.super, &c2.super, &r1.super }; Shape const *s; // 实例化矩形对象 Rectangle_ctor(&r1, 0, 2, 10, 15); Rectangle_ctor(&r2, -1, 3, 5, 8); // 实例化圆形对象 Circle_ctor(&c1, 1, -2, 12); Circle_ctor(&c2, 1, -3, 6); s = largestShape(shapes, sizeof(shapes)/sizeof(shapes[0]));printf(“largetsShape s(x=%d,y=%d) ”, Shape_getX(s), Shape_getY(s)); drawAllShapes(shapes, sizeof(shapes)/sizeof(shapes[0])); return 0;}输出结果:

largetsShape s(x=1,y=-2)Circle_draw_(x=1,y=-2,rad=12)Rectangle_draw_(x=-1,y=3,width=5,height=8)Circle_draw_(x=1,y=-3,rad=6)Rectangle_draw_(x=0,y=2,width=10,height=15)

总结

还是那句话,面向对象编程是一种方法,并不局限于某一种编程语言。用 C 语言实现封装、单继承,理解和实现起来比较简单,多态反而会稍微复杂一点,如果打算广泛的使用多态,还是推荐转到 C++ 语言上,毕竟这层复杂性被这个语言给封装了,你只需要简单的使用就行了。但并不代表,C 语言实现不了多态这个特性。

参考素材:

https://blog.csdn.net/onlyshi/article/details/81672279

编辑:jq

收藏 人收藏
分享:

评论

相关推荐

从0开始,181页知识带你轻松搞定C++语言

    C 语言作为结构化和模块化的语言,在处理较小规模的程序时,比较得心应手。但是当问题比较复杂,程序的规模较大的时...
发表于 07-24 13:10 0次 阅读
从0开始,181页知识带你轻松搞定C++语言

全志H616芯片香橙派OrangePi Zero2开发板连接USB以太网卡测试

1) 目前测试过能用的 USB 以太网卡如下所示,其中 RTL8153 USB 千兆网卡插入开 发板的 USB 2.0 Host 接口中...
发表于 07-23 18:18 101次 阅读
全志H616芯片香橙派OrangePi Zero2开发板连接USB以太网卡测试

PFC与EDEM软件各有什么优缺点

   PFC与EDEM软件的优缺点: 1) EDEM具有非常友好的图形用户界面,无论是前处理建模还是....
的头像 汽车玩家 发表于 07-23 15:11 64次 阅读
 PFC与EDEM软件各有什么优缺点

STM32操作系统系列使用C语言的教程

C语言,相对于汇编有更好的可读性,便于维护等优点。下面实验将使用C语言实现点亮LED灯。C语言与硬件....
的头像 汽车玩家 发表于 07-23 11:37 148次 阅读
STM32操作系统系列使用C语言的教程

基于STM32的多种printf用法

在调试代码的时候,最常用的就是使用printf函数来输出一些打印信息,提示自己代码的执行情况。 如果....
的头像 汽车玩家 发表于 07-23 11:12 42次 阅读
基于STM32的多种printf用法

嵌入式C语言编程小知识总结

1. 流水线被指令填满时才能发挥最大效能,即每时钟周期完成一条指令的执行(仅指单周期指令)。如果程序发生跳转,流水线会被清空,...
发表于 07-23 10:13 101次 阅读
嵌入式C语言编程小知识总结

用了这么多年的Linux CentOS,终于知道开机的流程了 精选资料分享

CentOS开机流程详解BIOS:(Basic Input Output System)基本输入输出系统,它是一组固化到计算机内主板上一个ROM芯片...
发表于 07-23 09:23 0次 阅读
用了这么多年的Linux CentOS,终于知道开机的流程了  精选资料分享

Linux系统SPI驱动总结(一)精选资料推荐

SPI是“Serial Peripheral Interface”的缩写,串行外设接口,是一种四线制的同步串行通信接口,用来连接MCU、传感器、...
发表于 07-23 08:34 0次 阅读
Linux系统SPI驱动总结(一)精选资料推荐

【 安信可平头哥模组TG-12F②】搭建Linux开发环境,二次开发直连阿里飞燕/天猫精灵平台,精选资料分享

文章目录一. TG-12F概述二、开发环境搭建获取SDK编译烧录一. TG-12F概述     TG-12F模块采用平...
发表于 07-23 07:51 0次 阅读
【 安信可平头哥模组TG-12F②】搭建Linux开发环境,二次开发直连阿里飞燕/天猫精灵平台,精选资料分享

linux查看设备信息和驱动安装信息 精选资料分享

lspci是列出所有的硬件信息,包括已经安装了驱动还是没有安装驱动的硬件设备,因为根据pci规范,只要改设备在pci总线上挂着,就可...
发表于 07-23 07:25 0次 阅读
linux查看设备信息和驱动安装信息  精选资料分享

微软转向,鸿蒙拥抱,炒房团都来了,Linux 为何引各方英雄竞折腰? 精选资料分享

作者 | 马超责编 | 夕颜出品 | CSDN(ID:CSDNnews)10年前人们常说“代码吞噬整个世界”,而现在人们又说“互联网的一...
发表于 07-23 06:26 0次 阅读
微软转向,鸿蒙拥抱,炒房团都来了,Linux 为何引各方英雄竞折腰? 精选资料分享

单片机脚本语言移植lua到stm32MDK的步骤

Lu a 是一个小巧的脚本语言。作者是巴西人。该语言的设计目的是为了嵌入应用程序中,从而为应用程序提....
的头像 汽车玩家 发表于 07-22 16:54 45次 阅读
单片机脚本语言移植lua到stm32MDK的步骤

STM32程序无法进入main函数的解决方法

很多人在基于STM32单片机项目开发过程中,会遇到STM32程序无法进入main的现象,在这篇文将分....
的头像 如意 发表于 07-22 16:18 53次 阅读
STM32程序无法进入main函数的解决方法

Linux内核架构和工作原理详解

简介作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址。目前支持模块的动态装卸(裁剪)...
发表于 07-22 08:47 0次 阅读
Linux内核架构和工作原理详解

linux内存管理

公交,地铁,睡前必备,方便大家查阅,持续更新,敬请期待!         ---更新于2020-02-12linux ...
发表于 07-22 08:41 0次 阅读
linux内存管理

俄罗斯将目光转向RISC-V,砸300亿卢布打造8核处理器

俄罗斯将目光转向RISC-V ,砸300 亿卢布打造8 核处理器   据俄国媒体爆料,俄罗斯国有企业....
的头像 E4Life 发表于 07-18 11:13 2779次 阅读
俄罗斯将目光转向RISC-V,砸300亿卢布打造8核处理器

Linux用户态开发驱动教程及基础知识

Linux用户态开发驱动教程及基础知识
发表于 07-14 10:06 16次 阅读
Linux用户态开发驱动教程及基础知识

Linux用户态开发驱动方法

用户态的驱动应用场景主要是以下几种,如果有其他的,希望各位朋友拍砖。
发表于 07-14 09:54 36次 阅读
Linux用户态开发驱动方法

liteos与linux区别

Huawei LiteOS自开源社区发布以来,围绕物联网市场从技术、生态、解决方案、商用支持等多维度....
的头像 汽车玩家 发表于 07-12 14:21 176次 阅读
liteos与linux区别

鸿蒙系统是什么语言开发的

华为鸿蒙系统作为华为的备用方案,首先必须要考虑的就是兼容性和开放性,这样更加自由的Linux自然就是....
的头像 汽车玩家 发表于 07-11 10:51 474次 阅读
鸿蒙系统是什么语言开发的

读取文件1个字节是否会导致磁盘IO?

在日常开发中一些看似司空见惯的问题上,我觉得可能大多数人其实并没有真正理解,或者理解的不够透彻。不信....
的头像 Linux爱好者 发表于 07-09 09:42 109次 阅读
读取文件1个字节是否会导致磁盘IO?

教你们C语言打印如何输出红色字体

除了Linux,在VS下也可以实现变色这一效果,先看下面的一段代码: #include 《stdio....
的头像 高速PCB硬件设计 发表于 07-08 12:48 185次 阅读
教你们C语言打印如何输出红色字体

鸿蒙和linux之间的关系是怎样的

在智能手机市场,谷歌的Android系统和苹果的iOS系统已经垄断了全世界99.9%的手机操作系统。
的头像 独爱72H 发表于 07-08 10:45 203次 阅读
鸿蒙和linux之间的关系是怎样的

鸿蒙的底层是安卓吗 鸿蒙是基于安卓吗

华为鸿蒙系统2.0自从上线后颇受国人追捧,作为全球首款主打“面向未来”、“万物互联”的分布式全场景操....
的头像 如意 发表于 07-07 15:08 428次 阅读
鸿蒙的底层是安卓吗 鸿蒙是基于安卓吗

浅析新塘031 串口PDMA通信

环境搭建这里就跳过了,没啥用,我还是用KEIL 5 开发,自行下载个PACK包安装就好了。点此前往新....
的头像 5G网通信 发表于 07-06 17:16 276次 阅读
浅析新塘031 串口PDMA通信

掌握这几种方法 你的接口查询速度将飞速提升

1. MySQL查询慢是什么体验? 大多数互联网应用场景都是读多写少,业务逻辑更多分布在写上。对读的....
的头像 C语言专家集中营 发表于 07-06 14:38 161次 阅读
掌握这几种方法 你的接口查询速度将飞速提升

基于OpenCV经典霍夫变换的一些内容

本文主要讲述的是霍夫变换的一些内容,并加入一些在生活中的应用,希望能对读者对于霍夫变换的内容有所了解....
的头像 ViTEX机器视觉 发表于 07-06 10:43 193次 阅读
基于OpenCV经典霍夫变换的一些内容

嵌入式图形界面设计工具TD Realizer V2.3.0新版发布

TD Realizer作为TD软件体系中的设计工具,是用户直接体验TD底层图形系统的入门引导,根据用....
发表于 07-06 09:27 215次 阅读
嵌入式图形界面设计工具TD Realizer V2.3.0新版发布

printf格式化输出符号参数详解

printf格式化输出符号参数详解
发表于 07-06 09:12 21次 阅读
printf格式化输出符号参数详解

什么是堆内存?堆内存是如何分配的?

在一般的编译系统中,堆内存的分配方向和栈内存是相反的。当栈内存从高地址向低地址增长的时候,堆内存从低....
的头像 电子发烧友网工程师 发表于 07-05 17:58 438次 阅读
什么是堆内存?堆内存是如何分配的?

超实用的任务优化与断点执行方案

前言 随着大数据时代的快速发展,企业每天需要存储、计算、分析数以万亿的数据,同时还要确保分析的数据具....
的头像 QNX 发表于 07-05 16:33 203次 阅读
超实用的任务优化与断点执行方案

C语言的函数调用程序和函数逆向分析

IDA可以很好地识别函数的起始位置和结束位置,如果在逆向分析的过程中发现有分析不准确的时候,可以通过....
的头像 5G网通信 发表于 07-05 15:52 146次 阅读
C语言的函数调用程序和函数逆向分析

eBPF是什么以及eBPF能干什么

一、eBPF是什么 eBPF是extended BPF的缩写,而BPF是Berkeley Packe....
的头像 Linux阅码场 发表于 07-05 15:17 175次 阅读
eBPF是什么以及eBPF能干什么

如何消除表面残余电荷和极化电场?

密度函数理论(DFT)已经发展成为电子结构计算的主要方法,几乎可以研究材料的所有方面及其特性。大多数....
的头像 知社学术圈 发表于 07-05 14:34 136次 阅读
如何消除表面残余电荷和极化电场?

米尔MYS-8MMX单板计算机的应用

MYS-8MMX单板采用NXP最新推出的i.MX8M Mini多核处理器,4XCortex-A53+....
的头像 汽车玩家 发表于 07-05 14:24 171次 阅读
米尔MYS-8MMX单板计算机的应用

Kubernetes容器网络基础

默认情况下,通过 network namespace 限制的容器进程,本质上是通过Veth peer....
的头像 C语言专家集中营 发表于 07-05 14:10 200次 阅读
Kubernetes容器网络基础

轻松高效地掌握Linux操作系统背后的原理

如今的软件开发行业,服务器端市场基本被 Linux 系统占领了。移动端中的 Android 系统是基....
的头像 CAE模拟设计支持平台 发表于 07-05 09:49 188次 阅读
轻松高效地掌握Linux操作系统背后的原理

Deskreen的功能有哪些?如何去使用Deskreen?

其它平台上的屏幕共享或屏幕镜像应用并不那么好。尽管大多数选项仅适用于 Windows/Mac,而你可....
的头像 阿铭linux 发表于 07-04 14:34 195次 阅读
Deskreen的功能有哪些?如何去使用Deskreen?

嵌入式开发中C语言源代码的应用优化方案

如果一个函数只在实现它的文件中被使用,把它声明为静态的(static)以强制使用内部连接。否则,默认....
的头像 MCU开发加油站 发表于 07-02 16:42 248次 阅读
嵌入式开发中C语言源代码的应用优化方案

改进VGG模型在苹果外观识别分类中的应用

改进VGG模型在苹果外观识别分类中的应用
发表于 07-02 14:52 18次 阅读
改进VGG模型在苹果外观识别分类中的应用

Linux内核Page Cache和Buffer Cache两类缓存的作用及关系如何

在我们进行数据持久化,对文件内容进行落盘处理时,我们时常会使用fsync操作,该操作会将文件关联的脏....
的头像 Linux阅码场 发表于 07-02 14:25 212次 阅读
Linux内核Page Cache和Buffer Cache两类缓存的作用及关系如何

如何将BusyBox移植到RT-Thread Smart下

BusyBox 是一个集成了数百个常用Linux/Unix命令和工具的软件。BusyBox 包含了一....
的头像 RTThread物联网操作系统 发表于 07-02 11:52 282次 阅读
如何将BusyBox移植到RT-Thread Smart下

Linux系统下传输大文件的切割与合并实例分析

往往是因为网络传输的限制,导致很多时候,我们需要在 Linux 系统下进行大文件的切割。这样将一个大....
的头像 C语言专家集中营 发表于 07-02 11:47 216次 阅读
Linux系统下传输大文件的切割与合并实例分析

Verilog HDL语言中任务与函数的比较

其中,返回值的类型和位宽是可选项,如果缺省会返回一位寄存器类型数据。Verilog HDL认为函数的....
的头像 FPGA之家 发表于 07-02 10:24 113次 阅读
Verilog HDL语言中任务与函数的比较

单靠硬件不够,RISC-V当前的系统支持情况如何

对于一个新生的架构来说,往往系统生态才是最难做好的一块。就拿Arm为例,Arm在成了移动霸主后,在桌....
的头像 E4Life 发表于 07-02 10:14 5105次 阅读
单靠硬件不够,RISC-V当前的系统支持情况如何

把进程绑定到某个 CPU 上运行是怎么实现?

昨天在群里有朋友问:把进程绑定到某个 CPU 上运行是怎么实现的。 首先,我们先来了解下将进程与 C....
的头像 阿铭linux 发表于 07-02 09:55 260次 阅读
把进程绑定到某个 CPU 上运行是怎么实现?

鸿蒙系统是基于什么开发的

鸿蒙系统作为华为的备用方案,首先必须要考虑的就是兼容性和开放性,这样更加自由的Linux自然就是首选....
的头像 汽车玩家 发表于 07-01 16:43 887次 阅读
鸿蒙系统是基于什么开发的

如何使用BPF对Linux内核进行实时跟踪

我们可以使用BPF对Linux内核进行跟踪,收集我们想要的内核数据,从而对Linux中的程序进行分析....
的头像 Linux阅码场 发表于 06-30 17:28 169次 阅读
如何使用BPF对Linux内核进行实时跟踪

想要快速入门Linux入门看这篇就够了

到底要如何Linux入门呢? 因为Linux的知识体系非常的庞大,IT行业很多领域都需要使用到Lin....
的头像 硬件攻城狮 发表于 06-30 16:03 238次 阅读
想要快速入门Linux入门看这篇就够了

单片机固件的应用与驱动分离设计的方式

今天跟大家找了一种常见的应用与驱动分离设计的方式,对于目前一些高性能MCU还是值得使用一下的,不过对....
的头像 硬件攻城狮 发表于 06-30 15:28 206次 阅读
单片机固件的应用与驱动分离设计的方式

复频率与时间函数两者之间的关系解析

复频率现在已是一个广泛熟悉而通用的名词,所以这里仍旧用它。复频率可以方便地表示在一个复平面上,如下图....
的头像 CAE模拟设计支持平台 发表于 06-30 15:27 122次 阅读
复频率与时间函数两者之间的关系解析

同源华安加入openEuler社区,将一起在虚拟化方向探索新发展方向

近日,致力于行业市场深入服务的基础软件提供商,北京同源华安软件科技有限公司(以下简称“同源华安”)签....
的头像 openEuler 发表于 06-30 14:50 284次 阅读
同源华安加入openEuler社区,将一起在虚拟化方向探索新发展方向

鲲鹏开发套件DevKit助力源代码迁移3大挑战

数字经济时代,市场既需要通用计算算力也需要异构计算算力。以ARM架构为代表的非x86体系架构正以其先....
的头像 华为计算 发表于 06-30 11:08 285次 阅读
鲲鹏开发套件DevKit助力源代码迁移3大挑战

基于OpenHarmony2.0 Canary在Linux环境下点亮3861开发板

在 OpenHarmony 2.0 Canary(金丝雀)6 月 2 日发布的同时,DevEco D....
的头像 发表于 06-30 09:23 282次 阅读
基于OpenHarmony2.0 Canary在Linux环境下点亮3861开发板

解读12 种 Numpy 和 Pandas 高效函数技巧

本文分享给大家 12 种 Numpy 和 Pandas 函数,这些高效的函数会令数据分析更为容易、便....
的头像 C语言专家集中营 发表于 06-29 17:05 286次 阅读
解读12 种 Numpy 和 Pandas 高效函数技巧

简述C语言中的内存泄漏的原理及解决方法

内存泄漏的原理 只有在堆内存里面才会发生内存泄漏的问题,在栈内存中不会发生内存泄漏。因为栈内存在自动....
的头像 5G网通信 发表于 06-29 14:58 183次 阅读
简述C语言中的内存泄漏的原理及解决方法

AM4379 AM437x ARM Cortex-A9 微处理器 (MPU)

TI AM437x高性能处理器基于ARM Cortex-A9内核。 这些处理器通过3D图形加速得到增强,可实现丰富的图形用户界面,还配备了协处理器,用于进行确定性实时处理(包括EtherCAT,PROFIBUS,EnDat等工业通信协议)。该器件支持高级操作系统(HLOS)。基于Linux的® 可从TI免费获取。其它HLOS可从TI的设计网络和生态系统合作伙伴处获取。 这些器件支持对采用较低性能ARM内核的系统升级,并提供更新外设,包括QSPI-NOR和LPDDR2等存储器选项。 这些处理器包含功能方框图中显示的子系统,并且后跟相应的“说明”中添加了更多信息说明。 处理器子系统基于ARM Cortex-A9内核,PowerVR SGX™图形加速器子系统提供3D图形加速功能以支持显示和高级用户界面。 可编程实时单元子系统和工业通信子系统(PRU-ICSS与ARM内核分离,允许单独操作和计时,以实现更高的效率和灵活性.PRU-ICSS支持更多外设接口和EtherCAT,PROFINET,EtherNet /IP,PROFIBUS,以太网Powerlink,Sercos,EnDat等...
发表于 09-25 11:51 323次 阅读
AM4379 AM437x ARM Cortex-A9 微处理器 (MPU)