栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言--1、编译链接

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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/103775488

Visual 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 = 100
		a = 50
	但是这里的修改是说,直接改代码,即
		define a =100	改为 define a =50

小结:
	一句话概括“宏”:起到压缩指令长度的作用
5、数据类型的概念,

%f代表以浮点型(float)的格式输出,

但是这样输出,输出的是“0.0000”

类似的,修改下图的两处,输出的也是0


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


来简单的说下原理,

printf不会自动进行类型转换。想要输出比较接近的结果,可是手动进行类型转换。

这样输出的是100,

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/977272.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号