一、程序编写思路
1、C程序的创建:
创建hello执行文件:
1、编写输出helloworld 的代码并保存为.c文件
2、执行以下过程:C源文件->预处理->编译->汇编->链接->可执行文件
完整过程:
-
预处理
gcc -E hello.c > hello.i
这个阶段处理源代码文件中的预处理指令,如宏定义的展开(#define
)、条件编译(#ifdef
, #ifndef
, #endif
)、包含头文件(#include
)等。
预处理器还会删除代码中的注释。
-
编译
gcc -S hello.i
编译器将预处理后的源代码转换成汇编语言。这个阶段会进行语法检查和语义检查,确保代码符合 C 语言的规范。
此时的汇编语言对于理解c语言编译过程很重要,可以查看该.i文件进行程序编译的解读。
编译器还会进行优化,比如消除冗余代码、循环展开、常量传播等。
注意这个地方的优化,涉及到嵌入式开发或者Linux系统编程时,编译器的优化对程序很不友好,需要涉及volatile类型的应用,来避免编译器优化的影响。
-
汇编
gcc -c hello.s
将汇编语言转换成机器代码。汇编器(assembler)读取编译器生成的汇编代码文件(通常以 .s
结尾),并生成目标文件(object file),通常以 .o
结尾。
-
链接->可执行文件(编译过程自动进行)
也可以使用链接器(linker)将一个或多个目标文件与库文件结合起来,生成可执行文件。
ld -o my_program main.o utils.o math_functions.o
链接器解析不同目标文件和库之间的外部符号引用,确保程序中的函数调用和变量引用正确链接到它们的定义。
一次性命令:
gcc hello.o -o hello
⚠️:最好用gcc hello.c -Wall(显示出所有的警告)
或者
gcc hello.c -o hello 或者 make hello
3、执行文件
:./hello
2、编写思路:
头文件:
c程序结构:
声明部分加主体实现部分
程序中运用的命令、函数一定要包含头文件
return:
return表示返回值,在void中执行完一个程序后,成功为0,不成功即为非0 值
子进程:调用主进程的命令
子进程在调用完后,主进程结束后,在终端命令行用echo $?打印上一条语句的退出状态。
例如打印helloworld是主进程,那return的值为10(加/n为11),即字数
注释:
可以用到声明部分之后函数之中,介绍程序或函数的作用和用法:
//
或者#if 0....一段代码....#
或者/* ....... * /
注意:有效函数和注释比例相当
man手册使用:
例如命令:man 3 printf
算法:
算法:解决问题的方法
形象化到:流程图、ns图、有限状态机fsm
二、数据类型:
1、数据类型参考资料:
数据类型需要和代码中的输入输出对应。以下是数据类型的分类图、64位系统环境中的占用大小和数据的属性。
可以作为资料参考:
2、数据大小:
每种数据类型都有自己的大小属性,在计算机中所有数据都是以二进制进行计算的,二进制的位数决定了这种数据类型的大小:
64位环境中:
8位bit 二进制数为 一个字节byte,1kb为1000字节。
我们所熟知的stm32就是32位的,他的ram大小是20kb,rom是64kb。
进制机制:
一个字节为4位,计算机中整数型转化为2进制后,不足其数据类型所占位数,则开头补0
(254)10 -> B11111110 (二进制)-> 0376(8进制)-> 0xFE(16进制)
补码:
-254 -> 254 ->11111110 -> 00000001 ->加1
00000010
浮点:
储存方式以整数部分为零,后32位为符号+精度+指数部分 跟0(或x)相比可能不能用==,所以要在判断语句后加上//if(fabs(a-x)<= 10e-6)
一般保留6位小数的精度
ASCII码:
0为048,A为065,a为097
000为null
010为回车
char型:
有无符号未被定义,存疑可以采用其他数据类型,char进行加减的时候A+1=B
不同数据类型互相转换:
1、往所占字节数比较多的类型靠拢(隐式转换)
2、强制类型转换(显式转化)