c语言在程序开发过程的各个阶段遇到的问题和知识总结

目录


前言

程序开发的六个阶段:

编辑-->预处理-->编译-->链接-->运行-->调试


一、编辑阶段

1、代码编辑器的好处:

智能提醒,自动补全,语法高亮,具有丰富的快捷键,可适配性强

2、常用的编辑器:

vim,vscode,nodpad++

3、优秀代码特点:

严格按照编程规范编写代码

可读性强

可扩展性强

可移植性强

二、预处理

预处理阶段会处理三个事情:

1、头文件

1、头文件中出现ifndef--define--endif是起什么作用:

答:防止重复包含

2、#include<xxx.h>和#include "xxx.h"的区别

答:<>是在系统的默认的标准头文件搜索路径下找该头文件;" "是先在当前路径下查找,找不到再去默认的标准路径下查找,所以" "的范围比<>大

3、头文件的作用

答:实现函数的自动化声明

4、头文件中可不可以进行全局变量的定义

答: 不可以,编译不会出粗,链接的时候会出现重复定义的错误,全局变量要定义在.c文件中,在别的文件中使用extern关键字扩展全局变量的使用范围

2、宏定义

不带参数的宏

#define 宏名 宏体

带参数的宏

#define 宏名(参数) 宏体

作用:代替频繁调用的短小函数

1、宏定义的作用

答:1、定义常量,提高代码的可读性

2、定义简单的函数宏(宏函数),提高运行效率,空间换时间

3、代码复用,频繁使用的代码段,可以宏定义,以提高代码的复用性

4、条件编译

2、编写两个宏

某一位设置1 #define setBits(data,n) data = data | 0x01<<n

某一位清楚0 #define clearBits(data,n) data = data & ~(0x01<<n)

3、定义带参数的宏,宏体加上括号

#define DIV(x,y) (x)/(y)

3、条件编译

1、概念

根据一个宏是不是被定义过作为条件,选择删除或者保留部分代码

2、形式:

形式1:
     #ifdef  标记
         代码
     #endif
形式2:
     #ifndef  标记
         代码
     #endif
形式3:
         #ifdef 标记
             代码段1
         #else
             代码段2
         #endif 

3、作用

(1)用在头文件中防止重复包含

xxx.h

#ifndef XXX_H

#define XXX_H

头文件内容

#endif

(2) 对工程起配置作用

比如单片机中的stm32f10x.h

(3)嵌套注释程序

三、编译

gcc常见参数

-E :只进行预处理,不进行编译、链接等后续步骤

例如:gcc -E test.c
-o :用于指定输出文件的名称

例如:gcc test.c -o myprogram
-I (大写i):用于指定头文件的搜索路径

例如:gcc -I/home/user/include test.c
-c :只进行编译,不进行链接,生成目标文件(以.o为扩展名)

例如:gcc -c file1.c file2.c
-L :用于指定库文件的搜索路径。在链接阶段,链接器需要找到程序所依赖的库文件(如.a静态库或.so动态库)

例如:gcc -L/home/user/lib test.o
-l (小写L):不是标准库,需要指定要链接的库名,库名一般是去掉前缀lib和后缀(如.a或.so)后的名字。例如,要链接libm.so(数学库),就使用-lm

例如:gcc test.o -L/usr/lib -lm
-static :用于强制使用静态库进行链接,默认是动态库链接

例如:gcc -static test.o -lfoo
-Wall :显示警告信息

例如:gcc -Wall test.c会在编译test.c时显示各种警告信息。
-g :生成调试信息

例如:gcc -g test.c
-On :用于优化编译后的代码(不与-g同时使用)

例如:gcc -O2 test.c会以-O2的优化级别编译test.c

四、链接

1、如何理解链接,为什么要进行链接?

单独编译,统一链接,所有的.o文件进行链接,和库文件进行链接,一个文件中使用到了另一个文件中的函数,不链接会出现链接错误

2、linkerror可能错误和原因分析

1、未定义的引用

原因:.c中的实现和.h中声明的名称不一致,或者.h中声明了,.c中没有实现

2、找不到库文件

原因:库文件未安装或者库文件版本号不一致,比如64位机安装了32位的库

3、重复定义:

原因:在头文件中不小心定义了函数或变量(而不是只进行声明),并且这个头文件被多个源文件包含,就会导致符号多重定义。

3、动态库和静态库

静态库 :将库中的代码和数据直接复制到最终的可执行文件中,所以静态链接后产生的可执行程序不需要库的支持,程序较大
静态库优点
独立性强 :可执行文件不依赖于外部库文件的存在,方便程序的分发和部署。即使在没有安装相应静态库的系统上,只要可执行文件本身完整,就可以正常运行。
稳定性高 :由于代码已经复制到可执行文件中,不用担心库文件版本变化或者被误删除、修改等情况影响程序运行。
静态库缺点
文件体积大 :因为库的代码会被复制到每个使用它的可执行文件中,所以会导致可执行文件体积增大。这在存储和网络传输时会占用更多资源。
更新维护不便:如果静态库的代码需要更新,那么所有使用这个静态库的可执行文件都需要重新编译链接,否则无法使用新的库功能。
动态库 :在程序编译时不会将库的代码和数据复制到可执行文件中。而是在程序运行时,由操作系统加载动态库到内存,并且多个程序可以共享同一份动态库的代码,动态链接产生的可执行程序需要库的支持,程序较小

动态库优点
节省存储空间和内存 :多个程序可以共享同一份动态库,减少了磁盘上存储的冗余代码,并且在内存中也只需加载一份,节省了内存空间。
更新方便 :如果动态库的代码需要更新,只要更新动态库文件本身即可,不需要重新编译所有使用它的可执行文件。程序在下次运行时会自动使用更新后的动态库。
动态库缺点
依赖管理复杂 :程序运行时依赖于动态库的存在,如果动态库文件丢失、损坏或者版本不匹配,程序将无法正常运行。这需要在系统中正确地管理动态库的安装、版本和路径等信息。
加载速度可能较慢:相对于静态库,动态库在程序启动时需要额外的加载过程,可能会导致程序启动速度稍慢,尤其是在动态库较大或者系统资源紧张的情况下。

4、使用第三方库的步骤

源码库 : 下载.c和.h文件,移动到项目路径下,包含头文件使用即可
二进制库

1、获取二进制库文件和相关头文件

2、了解库的使用文档和 API

3、配置项目以包含库和头文件,如在 Linux 系统下可以放在/usr/local/lib或项目指定的库目录中。对于头文件,也需要添加到项目的头文件搜索路径中

4、在项目中链接库


六、调试

1、怎么定位错误

1、使用printf打印三个宏:LINEFUNCTIONFILE

2、查看错误日志

3、使用调试器

2、调试器的主要功能:

1、设置断点
break 命令设置断点

break main会在main函数的第一行设置断点

break function_name会在function_name函数的入口处设置断点

break myfile.c:10会在myfile.c文件的第 10 行设置断点

2、单步执行
step (单步进入函数)
next (单步跳过函数)

3、查看变量的值

可以使用print命令查看变量的值,例如print variable_name可以查看variable_name变量的值

相关推荐
Eric.Lee202117 分钟前
AudioSegment 将音频分割为指定长度时间片段 - python 实现
开发语言·音频识别·音频分割
Tech Synapse24 分钟前
Java 动态设置 JVM 参数的方法
java·开发语言·jvm
宽广1 小时前
java aspose word 模板根据数据导出pdf
java·开发语言·pdf·c#·word
数据小爬虫@2 小时前
利用Python爬虫技术获取商品销量详情
开发语言·爬虫·python
字节高级特工2 小时前
C++---入门
开发语言·c++·算法
北辰浮光2 小时前
[JavaScript]Ajax-异步交互技术
开发语言·javascript·ajax
亦是远方2 小时前
C++编译过程
java·开发语言·c++
程序猿000001号3 小时前
使用Python的Turtle库绘制图形:初学者指南
开发语言·python
carlcarl09033 小时前
qt通过QAxObject操作word插入表格及数据,图片生成文档
开发语言·c#