C工程(项目开发)编程问题总结

在整个c文件工程中:
1、对于预处理指令的使用非常频繁,宏定义/引用头文件/条件编译;
其中引用头文件的作用,基本上初学者都很熟悉,在编译c源文件过程中,编译器(编译-汇编-连接)将引用的头文件内容贴到c源文件引用处,并最终汇总成一个总文件(【补充】:当然这个总文件是先由多个c源文件经过编译+汇编后生成各自的.obj文件[二进制文件],然后将多个.obj目标文件连接成一个整文件-.exe可执行文件),一般地,命名一个c源文件同时会命名一个.h头文件,方便识别和使用;
当工程中c源文件非常多的时候,源文件之间引用高耦合时,就会出现许多重定义(全局变量、函数等这些东西的使用高耦合)问题,例如整个工程中定义的源文件头文件有:a.c和a.h , b.c和b.h,其中a.c中部分要使用的全局变量和函数在a.h和b.h中都有定义,同时b.c中部分要使用的全局变量和函数在a.h和b.h中也都有定义,那么a.c中include的有a.h和b.h,b.c中include的也会有a.h和b.h,那么当你在IDE中编译单个源文件a.c或b.c时不会出现error,但是当整个工程进行编译连接的时候就会报redefinition;
那么条件编译的作用来了,例如:#ifndef _A_H #define _A_H …#endif 等等等这些,这样当整个工程文件进行编译连接的时候就不会出现重定义,使得头文件中定义的全局变量和函数都只能被贴一次(整个工程只出现一次),对于标识_A_H被定义过就不会再定义,这个可以随便书写名称(按理说);在单个文件进行编译时,也仅出现一次,所以条件编译就不影响单个源文件的编译还是整个工程的编译使用;
此外,对于全局变量的使用,消除重定义,可以用关键词extern,这样在使用其他文件中定义的全局变量时,在当前源文件使用处写例如: extern int a ;
/***********************************************************************/
**

接着上回书说道:

**
1》对于出现重定义的问题,无非是变量或者函数,一般在编写过程中,习惯于将普通变量如:int,char,struct,enum,union等若干个变量定义于各自所要用的.c源文件当中,而不在.h头文件中定义,只在.h文件中声明,但是在实际应用过程当中会出现例如:共用体嵌套结构体+位段等较为复杂的数据类型集群,这样很容易将它们集中到某.h头文件中,这样当该头文件被多个源文件include后,有可能出现单个源文件编译时没问题,但是整体连接过程就会报重定义的现象,因为什么呢?因为当你在IDE点击单独编译按钮进行编译当下源文件时,只是该源文件include的这个.h文件,其他包含该头文件的单独的源文件进行单独编译时也是这样,这样就巧妙的躲过了编译+汇编时的重定义;
【规则】变量有且只能有一次定义,但是可以声明多次,使用变量前必须定义或声明。一个项目中可以有多个源文件,但在所有的源文件中只允许出现一次对某个变量的定义。
这样的好处是避免当这个头文件被不同源文件include时出现重定义,有时候可能在编译过程中报不出错误,但是在连接的过程中才会报重定义错误,这是为什么呢?因为在编译过程中条件编译会起到避免重复编译的作用,这样很容易漏过,一旦编译过程中未报出,后续连接过程中就有可能报出重定义!!!
2》那么有人说了,不是有条件编译吗,为啥公共部分还会出现重定义,那是因为编译过程是各自源文件各自生存自己的.obj目标文件,所以条件编译从语法的角度是全程有效的,但是从实际物理生产文件的角度,连接过程是将之前的各自的源文件生成的目标文件集合到一起进行汇总,所以各自的目标文件中已经包含有公共的一套内容(定义在.h头文件中的变量/函数),所以相当于即使头文件中有条件编译了,但是在连接过程中还是会重定义;
3》但是有些IDE下编译不会报重定义,例如VC++6.0 ,就当它们是意外吧
4》当然了,对于变量的定义和声明形式要认识清楚:
例如 int i; int i=10; static int i 都是定义;
【补充】extern 关键字的基本解释:置于变量名或函数前,表示该变量或函数是定义在别的文件中,提示编译器+连接器遇到此变量或函数时去别的文件寻找其定义;
【补充】定义:为其分配了内存空间,指定了初始值;声明:向程序表明其类型和名字;
extern int i;是声明
extern int i = 10;是定义
所以在这里除了关键字extern外,其他都是定义;
5》永远不要在.h中定义变量,当然了理论上也是可以的,只是有很大可能会出现大量的在连接过程才会出现的重定义,不规范也麻烦;
6》将结构体,共用体,联合体等的嵌套的数据类型写到.h文件中。然后通过extern将以上数据类型的变量进行声明(一定要用extern进行声明),然后在要使用的源文件中include该头文件,然后正常进行声明和使用。当有多个源文件include该头文件时,在这些源文件中只能允许有一处变量前不加extern ,保证该变量只有一次定义;
/***********************************************************************/
**

接着上回书说道:

**
extern Uint8 hnbResetCellArm = 0;
extern Uint8 hnbResetCellArm ;今天又犯了一下这个错误,导致连接的时候重定义symbol multiply defined ;上面两个表达式赋值了表示初始化,即便是加external 也表示给该变量定义; 2022/08/11

/***********************************************************************/
keil多源文件工程,main.c声明extern int abc并使用abc、当却在bsp_xxx.c定义 int abc,两个源文件并不需要引用含定义变量abc的头文件,就可直接在各自源文件中用,但整个工程只允许有一处变量abc的定义;2022/09
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》汇川技术

(1)递减运算符示例:
在这里插入图片描述
在这里插入图片描述
(2)递减2,及有符号和无符号小减大后的结果:
在这里插入图片描述
在这里插入图片描述
(3)无符号/有符号条件判断,强制转换
在这里插入图片描述
在这里插入图片描述
2023/02/20
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》科沃斯机器人

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SUR0608

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值