C潜规则篇之如何实现平台无关

C潜规则篇之API接口 C语言模块化编程的基础是:把所有要隐藏的数据放在C文件中,所有要暴露给用户的信息放在API头文件,作为库和上层应用的桥梁。所以API头文件中的函数声明、数据类型等会被库自身和调用者共享。这就要确保库和上层应用的编译环境对它们有一致的解析,下列可能导致解析不一致的元素要格外注意:     1)char、enum这两个元素会被编译选项改变属性,因此最好不要直接出现在API接口中,如果非要包含,要注意 阅读详情

    或许大家都有这样类似经历:要在某平台上开发一个模块,很幸运找到了功能类似的参考代码,拿来修改却发现它是基于其它平台,底层接口完全不同,且全都嵌在代码里,要一个个改。面对一堆编译错误,用着麻烦,丢了可惜,真成了“鸡肋”。

    C代码复用不象JAVA那么简单,一般都要经过移植才能在不同平台运行。但如果事先把平台相关部分集中在一起,形成平台隔离层,C程序也能做到代码基本平台无关。判定C代码级平台无关的标准是:移植只需修改makefile等编译脚本,不需修改源代码。具体需要从以下方面提取和消除平台相关性,然后在makefile中切换不同平台的编译开关:

1)基本数据类型重定义

    类似下面代码,很多人都看到过,却不清楚为什么这样做:

    typedef int                           sint32

    typedef unsigned char           uint8;

    typedef signed char            sint8;

    typedef unsigned short          uint16;

    typedef unsigned int             uint32;

    用typedef可以为不同平台重定义一套通用数值类型,源代码里统一使用新定义类型名,移植时只需根据平台特性重新定义。注意:有的编译器默认char型为有符号,有的默认无符号,重定义时要明确指定signed或unsigned,否则不能消除平台相关性。

2)设计中间层平台库,完成标准库以及宏的重定义

    不要直接调用C标准库函数(如printf,malloc);不直接使用特定平台下的标准宏(如ASSERT , DEBUG等windows宏)以及编译器相关的语法,如#pragram等。这些元素平台相关,如果直接放在代码里,移植时就要修改源代码,应通过中间层隔离,例如:

    #define XXX_malloc   malloc  或 int XXX_malloc(){  return malloc();  }

    #define XXX_printf     printf    或 int XXX_printf(){  return printf();  }

    #define XXX_fopen    fopen   或 int XXX_fopen(){  return fopen();  }

    这样就不受平台底层变动的影响,甚至即使没有底层库支持也可以须改中间层库来移植,比如某些平台内存管理不完善,或申请的最大内存无法满足需要,这时就可以在中间层实现特定的内存管理。

   中间层接口的设计要尽量简化,移植的主要工作就是处理平台库接口,接口越简单,移植工作量就越少。

3)用编译开关加函数指针方式来选择不同平台的实现或特定优化版本

    有些如某FIR滤波器运算,针对不同硬件平台写了专门优化或汇编函数,函数指针可以为不同平台选择最优实现:

    void (*fir)(sint16 *pCoef);

    #if defined(ARMV4)

    fir = FIR_ARMV4;

    ……

    #if defined(TI_DM320DSP)

    fir= FIR_TIDM320;

    #if defined(ARM_CORTEXA9)

    fir = FIR_CORTEXA9;

    #endif

4)消除全局变量与静态变量

    某些平台(Symbian/Brew等)不支持全局变量,且全局与静态变量会使函数不可重入,并增加模块耦合性,可用两种方法代替:

    a. 用const把全局变量变为常量,很多全局数组本就只是存储只读常量数据,如:

      原始代码:const int *ptr[8] = {tab1,tab2,tab3,tab3,tab3,tab2,tab1,tab3};

      修正后代码:const int * const ptr[8] = {tab1,tab2,tab3,tab3,tab3,tab2,tab1,tab3};

    用const意味这些常数组将被定位到静态数据区,这是所有平台都支持的。

    b. 把全局变量组织到树状结构体集合中,定义一个handle指针,在程序内主要函数间传递信息,这样既能通过此handle全局访问数据,又避免出现语法上的全局变量。

5)某些平台(如PALM)不支持变长数组,应避免,如:

    不支持static const char sArray[][7] = {"Mike","Jerry","Tom","Henry","William"};

    事先指定长度:static const char sArray[8][7] = {"Mike","Jerry","Tom","Henry","William"};

6)有些编译器要求变量必须定义在函数开头所有表达式语句前,所以避免把局部变量定义在函数内部blocks中,即不提倡:

    int fun()

    {

      if (…… ){

        int tmp;   //某些编译器不支持此类语法

      }

    }

7)用sizeof代替长度值

    不同平台数据类型长度不同,int *p = malloc(10)这种定义直接移植到不同平台,或浪费内存,或内存越界。特别struct/enum等编译器相关,更是只能用sizeof取长度。

8)考虑字节序及字符集问题

    与设备字节序有关的代码,尽量兼容Little和Big Endian,提供两种字节序版本的IO接口,通过编译开关切换。另外考虑字符串资源的多平台管理维护,收集所有裸字符串,放在单独定义的头文件(资源文件),源码中用宏定义代替,便于后续字符编码集的扩展和移植。

9)指针类型变换时考虑到某些平台的内存对齐要求

    如下面代码在x86上正常运行,而ARM下就可能会crash:

    char x = malloc(15);

    ……

    if (0==((int *)x)[i])    //可能发生内存不对齐错误。

10)避免碰触C标准中的空白点

    C标准由于某些原因,把若干细节留给编译器自由实现,而这些空白区自然引起不同平台间的差异,要小心绕开,改用标准中明确定义的语法,这些其实已超出平台相关性问题,属于C的一些陷阱。如:

    a.不使用求值顺序不确定的表达式,如:while(i<n){  y[i]=x[i++];  }。 因为C没有限定=号左右的求值顺序,所以这里y[i]和x[i++]的计算顺序和结果与编译器相关,不同平台结果不同。因此要改为计算顺序确定的表达形式。

    b. 把有符号数的右移操作改为无符号,因为C标准没有规定有符号数右移的填充位,可能为0也可能为标志位,取决于编译器。

11)头文件中定义的函数以C接口形式提供,

    具体要求:a.函数参数不能用传引用方式;b. 不能用缺省参数;c. 不能用变长参数;d.所有接口API层函数必须显式用extern "C"声明为C接口,模板如下:

    #ifdef  __cplusplus

    extern "C" {

    #endif

    ……

    #ifdef  __cplusplus

    }

    #endif

12)设计时考虑栈空间容量,防止某些平台下栈溢出。

    具体措施包括:不影响效率时,不用大的临时数组,改用动态分配堆内存;避免使用递归函数以及太深的函数调用。

13)统一接口文件名大小写。

    某些编译器不区分文件名大小写(如VC6),另一些则区分(gcc),因此库接口头文件最好统一用小写命名,源代码中对应的include头文件名也小写,这样移植时就不需要因文件名大小写问题而修改源代码。常见于windows到linux的移植。

 

    差不多了,暂时只想到这些。基本上,做到这些你的代码就可以在不同平台上通行无阻了。

嵌入式面试的中的一些潜规则 而且,从心里角度来说,人们一般只会集中精力关注一个点,如果你的期望薪水高一点,那么他在考虑是否录取你时考虑的就是薪水问题,或者就是考虑你的技术问题,但是工资是老板发,技术是自己使用,所以从某方面来说如果有几个人与你技术差不多,但是从潜意识里,就会因为你的期望工资高而觉得你的技术好一点,最后录取你。或者我们换位思考一下,假设你是项目经理,你来招人帮你干事情,你会节约一点工资,去招技术差的,帮老板节约成本,自己慢慢来带人么,给自己找一大堆事情么?首先强调一点,对自己自信,并不是不尊重面试官; 阅读详情

相关推荐

【遥感数字图像处理(朱文泉)】各章博文链接汇总及思维导图

遥感数字图像处理(北京师范大学朱文泉教授)课程各章博文笔记汇总,及各章节思维导图

甜子yu的博客 2623

C为什么不能跨平台?

本文参考于https://www.cnblogs.com/jmsjh/p/7808764.html,由于只是简单的做一些笔记,难免出错,请包涵。 还有很多内容没有记录,详细内容请参考原文! 关于C不能跨平台性的分析 不管是使用的IDE直接点击个运行按钮还是使用gcc命令进行编译(gcc -o hello hello.c) ,得到最后的输出结果。但是实际上hello world程序的编译是这样...

wuqi5328的博客 6218

HarmonyOS ArkTS开发实战:用Axios封装一个通用的网络请求工具类(附完整代码)

本文详细介绍了如何在HarmonyOS ArkTS开发中利用Axios封装一个通用的网络请求工具类,涵盖架构设计、核心模块实现、UI状态联动及高级功能扩展。通过单例控制器、拦截器链配置和Token自动刷新机制,提升网络请求的稳定性和可维护性,适用于各类HarmonyOS应用开发场景。

weixin_30772105的博客 491

H.264视频I/O配套IC设计指南:从接口转换到调试实战

在视频采集、安防监控、工业视觉等系统中,H.264编码器的输入输出往往面临接口不匹配、时序对不齐、格式不统一等挑战,此时需要在主控与图像源之间引入视频桥接、串行器/解串器等配套集成电路(Companion IC)。这类芯片负责将HDMI、LVDS、MIPI CSI-2等多样化信号转换为编码器可处理的YUV格式,同时解决信号完整性、色彩空间转换、分辨率适配等关键问题。本文从系统工程角度出发,梳理H.264视频链路中配套IC的职责边界、输入输出通路设计要点,并结合寄存器级调试流程与真实踩坑案例,讨论花屏、延迟、

diaoju3333的博客 504

手把手教你从入门到精通C#串口通信

本文以我开发的串口助手SComTool为例,详细介绍《C#串口通信从入门到精通》专栏的目录内容,本专栏由一个高级工程师多年实战经验总结,绝对是c#串口通信的葵花宝典!带您从入门到精通C#串口通信!

qq_34059233的博客 3万+

sas协议(SAS PL-3)之Zoning功能

1 Zoning overview SAS zoning is implemented by a set of zoning expander devices with zoning enabled that define a zoned portion of a service delivery subsystem (ZPSDS)服务子系统. The zoning expander devices control whether a phy is permitted to participate in

sinat_37817094的博客 1533

C/C++中有关字长与平台无关的整数类型(c99)

     在C/C++中,整型的长度跟编译器相关,编译器的实现取决于CPU。 比如TC++是DOS16下的应用程序,DOS16是16位的操作系统,所以TC++中sizeof(int)==16;同理win32中sizeof(int)==32。     C99标准定义一个叫着的头文件,该头文件定义了一系列各种类别的整数类型typedef名字。尽管速多C++工具支持该头文件已经有一段时间了,

bryanj的专栏 1064

第069篇:浸入边界法进阶

浸入边界法(Immersed Boundary Method, IBM)是处理流固耦合问题的强大数值方法。本文深入介绍直接力法、反馈力法、Ghost Cell方法和多域IBM等高级技术。通过Python实现完整的IBM求解器,展示处理移动边界、弹性边界和多体相互作用的方法。浸入边界法,直接力法,反馈力法,Ghost Cell,流固耦合,移动边界,弹性边界Navier-Stokes方程添加体积力项:∂u∂t+(u⋅∇)u=−1ρ∇p+ν∇2u+f\frac{\partial \mathbf{u}}{\part

2401_87715305的博客 412

C语言的平台相关性,编译器相关性

C 标准的 Rationale 之一: 优先考虑效率,而可移植性尚在其次。      这就要求程序员非常清楚这些规则,如果你要写可移植的代码,就必须清楚哪些写法是不可移植的,应该避免使用。      另一方面,写不可移植的代码有时候也是必要的,比如 Linux 内核代码使用了很多只有 gcc 支持的语法特性以得到最佳的执行效率,在写这些代码的时候就没打算用别的编译器 编译,也就没考虑可移植性

ThinkHeart的博客 884

YoloV8改进策略:轻量级的CloFormer助力Yolov8在速度和精度上实现双双提升

CloFormer是清华大学在今年发表的轻量级主干网络,引入了AttnConv,一种attention风格的卷积算子。所提出的AttnConv使用共享权重来聚合局部信息,并配置精心设计的上下文感知权重来增强局部特征。AttnConv和普通attention的结合使用池化来减少CloFormer中的FLOPs,使模型能够感知高频和低频信息。这篇文章主要向大家讲解如何将CloFormer加入到YoloV8中。论文链接:https://arxiv.org/abs/2303.17803v5。

m0_47867638的博客 4312

某AI推荐系统项目管理复盘:架构师总结的6大方法论与调优策略

我是张三,某大厂资深AI架构师,主导过5个千万级用户的推荐系统项目(覆盖电商、内容、视频、音乐、外卖等场景)。我的公众号“AI架构师笔记”会分享更多AI项目管理和技术实战经验,欢迎关注。最后的话:推荐系统不是“一锤子买卖”,而是“持续优化的过程”。希望这篇文章能帮你少踩坑,多做对——毕竟,把复杂的事做成,才是架构师的核心能力。

2501_92132293的博客 362

C++ typedef详解

typedef的用途 1)定义一种类型的别名 注意typedef并不是简单的宏替换,如下例所示: int main() { char *pa,pb;//声明了一个指向字符变量的指针pa,和一个字符变量pb pa = "hello"; pb = "hello";//报错,不能将const char*类型的值赋给char类型的实体 pb = 'h';//正常 return 0; } 再看以下示例: int main() { typedef char* PCHAR

饭的笔记本 2万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

嵌入式 C 语言函数返回值的潜规则

关注、星标公众号,直达精彩内容素材来源:网络素材整理:技术让梦想更伟大|李肖遥基本上,没有人会将大段的C语言代码全部塞入 main() 函数。更好的做法是按照复用率高、耦合性低的原则,尽可能的将代码拆分不同的功能模块,并封装成函数。C语言代码的组合千变万化,因此函数的功能可能会比较复杂,不同的输入,常常产生不同的输出结果。C 语言函数的返回值C语言函数可以通过返回值表示输出结果,例如l...

李肖遥的专栏 497

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

C/C++“潜规则”之——默认返回值

相比C/C++”潜规则“之默认数据类型,这条”潜规则“个人感觉要更为隐晦,也更容易引发错误。 看代码: int Bar( void ) { if(FALSE) { return 1; } } int iResult = Bar(void); 请问: 1.上述代码能通过编译吗? 2.如果能的话,那么iResult的值...

norman_irsa的博客 2571

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

C潜规则篇之防止重定义

C程序编译时常出现类似xxx redefinition错误,除了模块间的命名冲突(命名污染及static),问题多数与头文件管理有关。大型C工程的头文件管理很麻烦:C源文件往往包含很多头文件,头文件又包含其他头文件,形成复杂的嵌套包含;C没有严格限定源文件和头文件的功能边界,二者都可以包含全局变量和函数等实体定义。这都可能导致类型或实体定义被重复包含和展开,使编译器抛出重定义错误。     解决

半山茶馆 1万+

绩效被打C了,谈谈「绩效考核」背后的逻辑以及潜规则

在新公司度过了一个完整的 Q3 季度,被打了绩效,也给下属打了绩效,感慨颇深。 今天就好好聊聊大厂打工人最最关心的「绩效考核」,谈谈它背后的逻辑以及潜规则,摸清楚了它,你在大厂这片丛林里才能更好的生存下去。 —1— 大厂的绩效到底有多重要? 先从公司角度,谈谈为什么需要绩效考核? 有一个著名的管理者言论,即:企业战略的上三路和下三路。 上三路是使命、愿景、价值观,下三路是组织、人才、KPI。下三路需要确保上三路能执行下去,否则便是空谈。那怎么才能达成呢? 马老板在湖畔大学的课堂...

m0_63437643的博客 1873

C潜规则篇之符号命名

C语言中如果能从名字看出符号(变量函数等)的类型和含义,就能一定程度上提高代码可读性,为此前人也总结出很多技巧,如著名的匈牙利命名法。不过每个人的盲点和兴奋点不同,预防与激励方法也不可能相同,所以各种命名法都有争议。这里只提醒大家注意好命名的作用,有意识地总结适合自己的方法,从而提高工作效率。下面是个人习惯,供参考:     1)宏定义和枚举常数全部用大写字母命名,在复合词里用下划线隔开每个单词

半山茶馆 1456

绩效被打C了谈谈「绩效考核」背后的逻辑以及潜规则

​编辑切换为居中添加图片注释,不超过 140 字(可选)在新公司度过了一个完整的 Q3 季度,被打了绩效,也给下属打了绩效,感慨颇深。今天就好好聊聊大厂打工人最最关心的「绩效考核」,谈谈它背后的逻辑以及潜规则,摸清楚了它,你在大厂这片丛林里才能更好的生存下去。— 1 — 大厂的绩效到底有多重要?先从公司角度,谈谈为什么需要绩效考核?有一个著名的管理者言论,即:企业战略的上三路和下三路。上三路是使命、愿景、价值观,下三路是组织、人才、KPI。下三路需要确保上三路能执行下去,否则便是空谈。

m0_63437643的博客 429

我知道的几条电商潜规则

一晃,也做几年的电子商务了,从C店到B店再到独网,成就不大,赚钱不少,目标依然清晰而坚定,今儿,抛砖引玉,说几条话糙理不糙的电商潜规则吧。 做得不如C,千万莫装B。 这话实在得很,在电商这行业,最理想的状态是资金碰上了懂行的。最郁闷的是没什么钱又在做B2C。在确定自己不够有钱不够懂行,就低下身段,学着先卖卖货吧,不管是开淘宝C店,还是怎么着都行,起码你得锻炼并养活下自己和自己可爱的团队吧。 ...

ff00yo的博客 380

C 语言函数返回值,竟也有潜规则~_c输出值是否可信(1),Kotlin可能带来的一个深坑

仔细考虑下,其实C语言函数使用返回值 0 表示成功是有原因的。更一般的C语言函数返回值并不一定只有两种可能值(成功/失败),它可能还会返回对应错误原因的返回值。总之,函数成功只有一种可能,函数失败却有多种可能。实数要么是 0,要么非 0,因此可以将 0 看作一个比较特殊的“唯一”数值,使用 0 这个“唯一”的返回值,表示唯一的“成功”,多种非零的返回值,表示多种原因的失败,无疑更好一些。

2401_84247101的博客 365

【C语言】C语言的潜规则:运行环境对C程序执行特性的影响

C 语言中有许多未定义行为(如整数溢出、空指针解引用),不同编译器和平台可能会表现不同。

猫猫的小茶馆 1307

软件测试员面试:从失败到成功的 10 点潜规则,经验分享篇

第3段是在C公司,做XXX,负责XX项目,带3个人;最后面试官不再提问的时候,可以主动提问,包括招聘的职位目前在做什么,要解决什么问题,甚至可以进一步询问面试官的总体感觉,自己和这个职位需求的匹配度怎么样,注意不是问是否通过了面试,另外不要在技术面试环节讨论薪资、加班等方面问题。我们曾听过这样一句话:“你是一份工作干了10年,还是真正工作了10年”,小编最近看到一篇关于面试的底层逻辑分析,也不禁产生这样的感慨,我们在过往的面试中,是"同样的经历复述了10次,还是有针对性调整的面试了10次"。

我的博客 807

C 语言函数返回值,竟也有潜规则~_c输出值是否可信

再比如,我们定义一个函数 myopen(),用于打开某个文件,那么,这个函数要么能够成功打开文件,要么打开文件失败,这时,可以通过返回值区分“成功”和“失败”。当然,C语言程序员中还有一种“行业潜规则”。实数要么是 0,要么非 0,因此可以将 0 看作一个比较特殊的“唯一”数值,使用 0 这个“唯一”的返回值,表示唯一的“成功”,多种非零的返回值,表示多种原因的失败,无疑更好一些。当然,myopen() 函数失败的原因可能很多,但不是本文关注的重点,本文更关心的是,该以何值表示“成功”,何值表示“失败”。

2401_84240431的博客 618

C/C++“潜规则”之——默认数据类型

原则上来说,C/C++是一种严格数据类型的语言,简单说,语法对于函数声明、赋值、传参等涉及到数据类型的地方都会有严格的验证和匹配规则。 但也有”例外“——C/C++的潜规则之默认数据类型。 这里举两个例子: 1.函数参数 bool DoSomething(unsigned Data); 上面的写法是合法的,可以通过编译,其中,Data的数据类型是unsigned int,即无符号整...

norman_irsa的博客 1176
上一篇: C潜规则篇之保持句法简单
下一篇: 补遗篇之static
ipmux
博客等级 码龄24年 161粉丝 65原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值