C语言(1)编译链接
文章目录
- 0、安装环境
- 1、C语言的第一个程序
- 2、C语言的编译过程
- 3、变量
- 4、常量
- 4.1、const
- 4.2、宏
- 5、数据类型的概念,
C语言只可以修改内存,汇编还可以操作寄存器。
本系列文章不适合纯小白看,更适合有一定编程基础来看
0、安装环境
gcc安装参考,
https://blog.csdn.net/jiqiren_dasheng/article/details/103775488Visual Studio 2019运行C参考,(推荐2019版本)
https://zhuanlan.zhihu.com/p/132445107
快捷键进行注释与接触注释:
注释 : Ctrl + k + c取消注释 : Ctrl + k + u
1、C语言的第一个程序
软件直接安装VC,新建选择空项目,项目名称任意,

稍微改一下后缀,

先操作一个显存,输出一个最经典的hi,
std 是标准的意思,io 就是流(输入、输出)h 就是头的意思,
然后,调用printf函数来直接做输出,接着使用main函数将printf函数包含,告诉操作系统,这个是入口。这个main函数,可以有返回值,也可以没有返回值。没有返回值,就在main函数之前加一个 void,
最终代码如下,点击调试器即可。
可以看到程序执行完毕之后,直接退出。

接着我们想要将电脑的计算器程序打开,就可以直接使用system函数,
当然,system函数,也需要导入一些库,即标准的lib库,具体代码如下:

当然也可以,将程序打印完内容之后“暂停”,

运行程序,这个输出完指定内容之后,直接暂停并没有和之前一样结束。

2、C语言的编译过程
接着我们来研究C语言程序的编译过程,将上述的代码保存到test.c文件内。cmd之后输入gcc -v,这个可能需要配置环境变量,

使用命令将test.c编译,

C语言编译的第一步被称为“预编译”,这个预编译都干什么?
1、将头文件展开,即导入的stdio.h、stdlib.h具体函数全部导入程序2、宏定义替换3、删除代码中的注释
第二是,宏定义替换(将变量替换为具体的值)
即预编译的第二步,将第五行的“乃子”替换为100

当然,在实际的测试中,gcc的编译不支持变量名称用中文定义。
将代码换下,“乃子”换为“a”

继续使用gcc编译test.c,可以看到最后这个a已经变为了100
同时看到注释也被删除

完成预编译之后,就是将代码编译为汇编语言了,
使用以下命令,将编译后的文件保存到test.s文件内,

打开test.s文件,这个汇编可能与部分同学学习的汇编感觉不一样呢?
其实只是语法的不同,该汇编语法是贝尔实验室的汇编语法(AT&T汇编)
该汇编语法常用于Linux上边,一般Linux逆向都会使用到该语法。多说一点,在win系统上常用的汇编为win32

最后一步是二进制的转换,直接“-c”即可,

会生成一个“O文件”,

打开内容看看,

转一下16进制,

转化之后,

但是这种“O文件”还是操作系统无法直接执行的。执行是要操作系统把对应的二进制交给CPU,才能执行,即必须变为操作系统认识的“样子”,在win系统上就是“pe”文件,即“.exe”
这个将“O文件”变为操作系统可识别的过程被称为“链接阶段”直接什么参数都不加,就直接变为可执行的程序了,

双击生成的“exe”文件,

小结:
C语言的编译分为4步,预编译(具体作用参考上边)编译(将预编译的结果编译为汇编)二进制转换(将汇编转换为二进制文本)链接阶段(将二进制变为操作系统可识别的程序)
3、变量
变量的本质是一片连续的内存,比如:int a =100 、、代表可以通过“a”这个“符号名”访问到这个“100”的内存,
代码运行看看,输出a的内存地址之后,打个断点,

将a的地址打印输出,

将内存地址复制出来,查找一下;
可以先调整为“4字节整数”,

第一个是16进制的64,转化为10进制就是100,

假设我们将,这个“64”改为 别的值(实际测试这个VC貌似没有找到修改的地方),
再次打印a的地址,这个地址是会变化的。
4、常量
4.1、const
C语言,正常的定义常量的方式,是在变量之前加一个“const”,这样下边假设再有想改变a变量的参数如a“ = 50”就会直接报语法错误,
第八行的,“%d”是以整数输出,变量a的值。

然而,这种“const”定义的常量并不是真正意义上的常量,是可以被修改的。
通过下边“修改内存”的间接方式就可以达到修改变量a的值的效果,(&a),取出a变量的地址,*符号,根据内存地址取出内容,a变量是int类型的,这里要进行类型转换,即(int*)的作用

直接输出40,

怎么样的常量算是“真正的”常量内,即"define"关键字定义的,
通过define关键字定义的常量,在取地址的第一步就会报语法错误,

题外话--------以下内容个人理解
这个原因是什么,
首先要明白,a=100的本质,
a会被分配一块内存,但是这个100是寄存器生成的,然后把生成的100放到了a的内存。
修改a的值,即寄存器生成一个新的值50放到内存中,然后让a指向这个新的50
因为取地址是取得a的地址,所以就会造成a这个变量的值可以随意变化,但是define是直接取得“100”的内存(跨过了a这个“中间商”)当然,这个define只能是C语言中,真正的常量,还是可以通过汇编达到修改a的效果。
主要是C语言不能操作寄存器,
4.2、宏
题外话
define被称为“宏定义”,这个“宏”是什么含义呢这个宏,其实是被直接翻译过来的,本质是“macro”,其作用就是“缩短代码”,其实这个作用和“传统意义上的函数的作用一致”,define a = asdasdasdaa很多很多,很长很长的指令asdasdasads假设下边很多地方都要使用到这个“asdasdasdaa很多很多,很长很长的指令asdasdasads”那在之后想修改程序要修改很多的地方,但是经过“宏定义”之后,仅仅修改a后边的值,别的调用a值的地方,自然会跟着修改。一个问题是,不是说define定义的不能被修改吗,这怎么又提到修改了,不能被修改是程序执行的修改如:define a = 100a = 50但是这里的修改是说,直接改代码,即define a =100 改为 define a =50小结:一句话概括“宏”:起到压缩指令长度的作用
5、数据类型的概念,
%f代表以浮点型(float)的格式输出,

但是这样输出,输出的是“0.0000”
类似的,修改下图的两处,输出的也是0

再次稍微修改,直接输出了“负数”,

来简单的说下原理,
printf不会自动进行类型转换。想要输出比较接近的结果,可是手动进行类型转换。
这样输出的是100,

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
