您的位置:首页 > 科技 > 能源 > 阐述建站流程_品牌怎么注册_百度下载安装到手机_优化网站性能

阐述建站流程_品牌怎么注册_百度下载安装到手机_优化网站性能

2024/11/16 10:42:33 来源:https://blog.csdn.net/2301_78863061/article/details/143642753  浏览:    关键词:阐述建站流程_品牌怎么注册_百度下载安装到手机_优化网站性能
阐述建站流程_品牌怎么注册_百度下载安装到手机_优化网站性能

文章目录

  • main函数很普通
    • main函数之前调用了什么
    • main函数和自定义函数的对比
  • 变量名只为人而存在
  • goto是循环的本质
  • 指针变量
    • 指针是一个特殊的数字
      • 汇编层面看指针
    • 数组和指针
      • 数组越界问题
        • 低端地址越界
        • 高端地址越界
    • 引用就是指针

main函数很普通

main函数是第一个被调用的函数吗?在用户视角看来main函数的确程序的入口,但是在CPU视角下,main函数仅仅只是一个普通函数,和用户自定义的其他函数没有任何的区别。

main函数之前调用了什么

Linux环境:

_start->__libc_start_main->main

在这里插入图片描述

每一个Linux进程的入口函数都是_start,_start是一段直接由汇编语言编写的函数,它负责的工作就是把程序的命令行参数以及环境变量压入栈中,此时环境变量和参数一起存放在一个数组中

为了把环境变量单独提取出来,_start紧接着会调用__lib_start_main函数构建一张环境变量表,并进行一些全局变量的初始化工作,随后再进入main函数执行用户程序,再main函数退出时进行收尾操作例如全局变量的释放。这么一来,main函数似乎也只不过是一个被调用的函数,它只是默认被注册为用户代码的入口而已,也就是说,用户代码入口不一定非要是main函数

main函数和自定义函数的对比

一直以来我们编写C/C++程序时都是约定俗成地添加一个main函数来启动程序(因为不这么做往往会报错),这种情况一度让不少人认为main函数具有特殊的地位,能够得到CPU的青睐,其实不然,CPU眼中main函数啥也不是就是很普通的函数

int main(){return 0;
}
int func(){return 0;
}

通过汇编观察main和func的区别,会发现它们所对应的汇编指令居然完全一致

main:push rbpmov rbp, rspmov eax, 0pop rbpret
func:push rbpmov rbp, rspmov eax, 0pop rbpret

2个函数所做的操作都是一样的

  1. 建立函数栈帧 push rbp / mov rbp,rsp
  2. 将返回值拷入寄存器 mov eax,0
  3. 释放函数栈帧并返回 pop rbp / ret

gcc有一个命令可以改变用户代码的入口,使得用户指定其他函数作为程序起点

gcc -nostartfiles -efunc test.c

意思是编译test.c不使用系统的标准启动文件,将程序起点设置为func函数;一般不推荐这么做,因为使用标准启动文件代表着你需要自己为func瞻前顾后,这无疑是在自找麻烦

变量名只为人而存在

变量对程序员来说并不陌生,我们无时无刻都在使用变量帮助我们记忆,因为一个好的变量名可以大大提高源代码的可读性;尽管如此,对于可执行文件来说它并不需要存储所谓的变量名(release模式编译链接),CPU只需要知道一个逻辑地址就可进行读写操作,也就是说在发布模式编译链接时所有的变量名都会被转换称逻辑地址。

因此,我们可以给出关于变量的定义:=变量就是逻辑地址的一个别名,它向上以字符串形式以供人阅读记忆,向下被转成地址值供CPU访存

int a=0;
int main(){a=2;return 0;
}

所对应的汇编文件

main:push   rbpmov    rbp,rspmov    DWORD PTR [rip+0x0],0x2        # e <main+0xe>//将立即数0x2写入到rip值偏移量为0的位置,DWORD PTR标识4字节mov    eax,0x0pop    rbpret

可以看出a=2这条代码所对应的汇编是mov DWORD PTR [rip+0x0],0x2,CPU只需要通过几个逻辑地址相对寻址就可以确定内存的哪个位置需要被赋值为2

goto是循环的本质

虽然说不鼓励在编写C/C++程序时随意的使用goto,但是不代表goto不值得探究,早期的循环其实都是通过goto语句来实现的,只不过随着程序越来越大,过多的goto语句打破了程序的结构性使得源码难以维护,进而衍生出了结构性更强的for、while、do语句,它们都是在底层实现上都继承的goto的机制

void test_for(){for(int i=0;i<10;++i){}
}
void test_while(){int i=0;

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com