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,

在这里插入图片描述


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

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部