php怎么赋值为对象,函数的返回值返回到main函数后?
根据所用编译器和CPU的不同,以及返回值数据类型的不同,C语言中的函数返回值可能通过寄存器传递,也可能通过栈传递。对大多数CPU和编译器来说,出于性能考虑,能使用寄存器传递的,尽量使用寄存器传递,只有当寄存器不够用的时候,才会通过栈传递。
针对这两种情况,我分别举个x64 + GCC环境下的例子来说明。
通过寄存器传递返回值如下图中的一段简单的代码,返回值是一个有符号整数类型
我们看下x64/GCC下面对应的汇编代码:
test函数中的
1129: mov $0x2,%eax
便是把返回值2存放到eax寄存器中。而main函数中的
113d: callq 1125 <test>
1142: mov %eax,-0x4(%rbp)
则先调用test函数,然后把返回值从eax中取出,并存放到rbp 4的地址处,也就是赋值给局部变量a。
通过栈传递返回值下面这个例子中,test()函数返回一个结构体struct result。(注:这里只是为了演示用栈传递返回值,实际项目中不建议函数直接返回结构体,可以用结构体指针代替)
(这个例子第一眼看上去会有些许复杂,千万不要懵逼,汇编代码不是洪水猛兽,掌握一些基本的汇编代码对修炼内功、调试问题都是大有裨益的:)
在x64/GCC环境下的汇编代码如下:
先看main()函数:
我们先看main()函数中调用test()的几条指令:
ret = test();
11dd: lea -0x50(%rbp), %rax
11e1: mov %rax, %rdi
11e4: mov $0x0, %eax
11e9: callq 1135 <test>
11dd和11e1两条指令的作用是把栈地址rbp 0x50存放到rdi寄存器中,我们暂且不去管这个地址是用来做什么的,等看了test()函数之后自然就会明白。后面两条指令是把eax清零,然后调用test()函数。
test()函数的汇编代码如下:
test()的汇编看起来是不是有点复杂呢?不要紧张,其实做的事情很简单,就是给局部变量r分配栈空间,然后对它进行初始化,然后把r的值存放到一个内存地址当中,最后把这个内存地址放到rax寄存器中,并返回出去。我们仔细分析一下:
1139: mov %rdi, -0x28(%rbp)
这条指令是把rdi寄存器的值存放到栈空间rbp 0x28的地址处。还记得rdi寄存器中存放的是什么吗?回想一下,在main()函数调用test()函数之前,是不是把一个地址存放到rdi寄存器中了呢?忘了的话,再去看一下。我们先不管这个值用来做什么,只要记得,test()函数把main()函数传递过来的一个值存放到了一个栈地址当中。
接下来的这几条指令,就是对局部变量r进行初始化:
struct result r = {1, 2, 3, 4};
113d: movq $0x1, -0x20(%rbp)
1145: movq $0x2, -0x18(%rbp)
114d: movq $0x3, -0x10(%rbp)
1155: movq $0x4, -0x8(%rbp)
下面就要把r的值返回出去了,我们来看看编译器是怎么做的,先看这几条指令:
return r;
115d: mov -0x28(%rbp), %rcx
1161: mov -0x20(%rbp), %rax
1165: mov -0x18(%rbp), %rdx
1169: mov %rax, (%rcx)
116c: mov %rdx, 0x8(%rcx)
115d这条指令,是把栈中rbp-0x28处的值放到rcx寄存器中,还记得这个地址存放的值是什么吗?对了,就是test()入口处从rdi中取出来的那个值,也就是main()函数通过rdi寄存器传递给test()的一个值。然后,1161和1169两条指令把r.a值存放到rcx寄存器指向的地址处,1165和116c两条指令把r.b的值存放到rcx寄存器指向的地址再偏移8的位置处。
现在我们再来回过头想一下,main()函数通过rdi寄存器传递给test()函数的那个值是用来做什么的呢?对了,那个值其实就是存放test()函数返回值的那块内存的地址。
那么记下来的几条指令就比较容易理解了:
1170: mov -0x10(%rbp), %rax
1174: mov -0x8(%rbp), %rdx
1178: mov %rax, 0x10(%rcx)
117c: mov %rdx, 0x18(%rcx)
1170和1178把r.c存放到rcx + 0x10地址处,1174和117c把r.d存放到rcx + 0x18地址处。
到这里为止,test()函数已经把局部变量struct result r的所有字段的值全部存放到main()函数通过rdi寄存器传递给test()的那个内存地址中。
最后,看一下剩下的几条指令:
1180: mov -0x28(%rbp), %rax
1184: pop %rbp
1185: retq
1180指令把rbp 0x28处的值rax中,也就是把存放返回值的那块内存的地址,存放到rax寄存器中,最后返回出去。
到这里,是不是清晰多了呢?我们再来一下这个过程:
main()函数把一个栈空间中的地址rbp 0x30通过rdi寄存器传递给test()函数test()函数从rdi寄存器中取得这个地址,然后把要返回的值存放到这个地址指向的内存中test()把这个地址存放到rax寄存器中,并返回给main()函数掌握一定汇编知识的重要性可能对于很多童鞋来说,汇编语言比较晦涩难懂,难以掌握。确实,作为一个最为接近机器语言的编程语言来说,汇编确实比较晦涩,除了一些做底层系统软件的童鞋外,日常工作中直接用汇编写代码的机会确实不多,但是,这并不意味着掌握汇编语言就毫无用处。
掌握一定的汇编知识,会对整个计算机的原理和体系结构有更深入的理解,很多东西都能够知其然并知其所以然。尤其那些对底层系统软件感兴趣的童鞋,如BIOS/bootloader、OS内核、设备驱动、编译器、虚拟机等,汇编语言更是必须要掌握的。有些做上层应用的童鞋,如前端开发等,平时用到汇编的机会不多,但是在调试一些问题的时候,如果能够了解一些汇编知识,就会如虎添翼,事半功倍。
总之,不管所用的开发语言是C/C++还是Java、Python、PHP、Javascript,不管是做系统软件开发,还是做前端开发,只要是有志于干程序员这一行当的,掌握一定的汇编,对完善自己的技术知识体系,增强自己调试问题的能力,和对计算机体系结构的理解都大有裨益。
思考题能坚持读到这里,我想你已经基本清楚C语言的函数返回值是怎么传递的了。
那么,不妨思考一下,C语言的函数参数又是怎么传递的呢?😁欢迎留言,或者私信讨论,要是有人感兴趣,我可以写篇文章介绍一下。
最后,对这个问题有不清楚的地方,欢迎留言讨论。也欢迎关注,我计划在接下来的一段时间,更新一些偏底层的东西,如Linux kernel(e.g. memory management、process management、scheduling、timekeeping, etc.)、KVM/Qemu virtualization、compiler、debugger等,有兴趣的童鞋欢迎关注,互相交流学习。
PHPJavaPythonC?
如果把编程语言比作国家的话:
PHP:巴西。拥有很多美好的事物,经常炫耀自己,但私底下其实非常保守。
Java:美国。乐观,强大,喜欢把麻烦事掩盖起来。
Python:荷兰。时髦,富有,平易近人,有吸引力,但并不是表现最佳的。
C:挪威。强势,动态,但无法令人感到激动。
C++:英国。强大,严谨,但并不擅长于干实事,逐渐被Java取代。
如果把编程语言比作车的话:
PHP:Oscar Mayer Wienermobile。外形奇特,难以驾驭,但每个人都想驾驭它。
Java:家庭旅行车。驾驶起来很容易,速度不会太快,不容易车毁人亡。
Python:适合初学者使用的车。可以无照驾驶,适合在路况好、车速<30码的地方行驶。
C:赛车。跑得很快,但它可能每50公里就抛锚一次。
C++:C赛车的升级版。它除了拥有C赛车的功能,还增加了许多新功能。例如它每250公里只抛锚一次,但是一旦它抛锚,基本上没人能找出是什么地方出了错。
--------------------------------以下是几种语言的特点-----------------
PHP
优点:
1. 跨平台,性能优越
跟Linux/Unix结合比跟Windows结合性能强45%,并且和很多免费的平台结合非常省钱。
2. 语法简单,容易上手
PHP有成熟的开发工具,比如NuPHPed,在Linux平台下可以使用Eclipse等等。
3. 技术支持性好
很多技术工具,比如WebService、Ajax、XML等等,足够应用;还能够使用多种数据抽象层,模板层,方法。
4.框架多且成熟
比如支持MVC的框架:phpMVC,支持类似http://ASP.net的事件驱动的框架:Prado,支持类似Ruby On Rails的快速开发的框架:Cake等等,足够满足你的应用需求。
5.面向对象体系,能够适应基本的面向对象要求。适合开发大型项目。
6..开源性
比如比较知名的开源框架有Zend Framework、CakePHP、CodeIgniter、symfony等,开源论坛有Discuz!、Phpwind等,开源博客 WordPress,开源网店系统如Ecshop、ShopEx等,开源的SNS系统如UCHome、ThinkSNS等。
缺点:
1.对多线程支持不太好,大多数时候我们只能简单的模拟去实现的。
2.语法不太严谨,比如变量不需要定义就可以使用,在c,Java,c++中变量是必须先定义以后才可以使用的。
3. PHP的解释运行机制繁琐。
Python
优点
1.易于学习
python虽然是用c语言写的,但是它摈弃了c中非常复杂的指针,简化了python的语法,它使你能够专注于解决问题而不是去搞明白语言本身。
2.开源性
Python是FLOSS(自由/开放源码软件)之一,Python希望看到一个更加优秀的人创造并经常改进。
3.可移植性
Python经过改动,已经被移植在许多平台上了。另外,Python解释器把源代码转换成称为字节码的中间形式,然后再把它翻译成计算机使用的机器语言并运行,因而,你只需要把你的Python程序拷贝到另外一台计算机上,它就可以工作了,这也使得你的Python程序更加易于移植。
4.面向对象面向过程同时支持。
5.可扩展性和可嵌入性
你可以将Python嵌入到C/C++程序,让你的程序的用户获得"脚本化"的能力。
6.标准库以及第三方库资源丰富
Python标准库确实很庞大。python有可定义的第三方库可以使用。它可以帮助你处理各种工作,包括正则表达式、文档生成、单元测试、线程、数据库、网页浏览器、CGI、FTP、电子邮件、XML、XML-RPC、HTML、WAV文件、密码系统、GUI(图形用户界面)等等。
缺点
1.运行速度慢,相比于C++/C运行速度偏慢,不过对于用户而言,机器上运行速度是可以忽略的。
2.构架选择太繁杂,没有像C#这样的官方.net构架,也没有像ruby由于历史较短,构架开发的相对集中,所以人人都有不同的方案。
Java
优点:
1. 跨平台性
Java语言中, Java自带的虚拟机很好地实现了跨平台性。 Java虚拟机提供了一个字节码到底层硬件平台及操作系统的屏障,使得Java语言具备跨平台性。
2. 面向对象
Java是一种面向对象的语言,也继承了面向对象的诸多好处,如代码扩展、代码复用等。
3. 安全性
运行时Java类需要类加载器载入,并经由字节码校验器校验之后才可以运行。 Java类在网络上使用时,对它的权限进行了设置,保证了被访问用户的安全性。
4. 多线程
Java除了内置的多线程技术之外,还定义了一些类、方法等来建立和管理用户定义的多线程。
5. 简单易用
Java源代码的书写不拘泥于特定的环境,可以用记事本、文本编辑器等编辑软件来实现,然后将源文件进行编译,编译通过后可直接运行,通过调试则可得到想要的结果。
缺点:
运行速度相比于C/C++有些缓慢了,这是机制原因导致的。
C
优点:
1. 简洁紧凑、灵活方便
C语言一共只有32个关键字,9种控制语句,程序书写自由,主要用小写字母表示。它把高级语言的基本结构和语句与低级语言的实用性结合起来。 C 语言可以象汇编语言一样对位、字节和地址进行操作, 而这三者是计算机最基本的工作单元。
2. 运算符丰富
C的运算符包含的范围很广泛,共有种34个运算符。C语言把括号、赋值、强制类型转换等都作为运算符处理。从而使C的运算类型极其丰富表达式类型多样化,灵活使用各种运算符可以实现在其它高级语言中难以实现的运算。
3. 数据结构丰富
C的数据类型有:整型、实型、字符型、数组类型、指针类型、结构体类型、共用体类型等。能用来实现各种复杂的数据类型的运算。并引入了指针概念,使程序效率更高。另外C语言具有强大的图形功能, 支持多种显示器和驱动器。且计算功能、逻辑判断功能强大。
4.C是结构式语言
结构式语言的显著特点是代码及数据的分隔化,即程序的各个部分除了必要的信息交流外彼此独立。这种结构化方式可使程序层次清晰, 便于使用、维护以及调试。C语言是以函数形式提供给用户的,这些函数可方便的调用,并具有多种循环、条件语句控制程序流向,从而使程序完全结构化。
5. C语法限制不太严格、程序设计自由度大
一般的高级语言语法检查比较严,能够检查出几乎所有的语法错误。而C语言允许程序编写者有较大的自由度。
6. C能直接访问物理地址和操作硬件
因此既具有高级语言的功能,又具有低级语言的许多功能,能够象汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元,可以用来写系统软件。
7. C语言程序生成代码质量高
程序执行效率高一般只比汇编程序生成的目标代码效率低10へ20%。
8. C语言适用范围大,可移植性好
C语言有一个突出的优点就是适合于多种操作系统, 如DOS、UNIX,也适用于多种机型。
另外
C语言具有绘图能力强,可移植性,并具备很强的数据处理能力,因此适于编写系统软件,三维,二维图形和动画它是数值计算的高级语言。
缺点:
运算符和运算优先级过多,不便于记忆,语法定义不严格,编程自由度大,对新手不友好。
C++
C++除了兼具了C语言的优势之外,还有一下特点:
C++语言的主要特点表现在两个方面,一是尽量兼容C,二是支持面向对象的方法。
它操持了C的简洁、高效的接近汇编语言等特点,对C的类型系统进行了改革的扩充,因此C++比C更安全,C++的编译系统能检查出更多的类型错误。
另外,由于C语言的广泛使用,因而极大的促进了C++的普及和推广。C++语言最有意义的方面是支持面向对象的特征。虽然与C的兼容使得C++具有双重特点,但他在概念上完全与C不同,更具面向对象的特征。
出于保证语言的简洁和运行高效等方面的考虑,C++的很多特性都是以库(如STL)或其他的形式提供的,而没有直接添加到语言本身里。C++引入了面向对象的概念,使得开发人机交互类型的应用程序更为简单、快捷。很多优秀的程序框架包括Boost、Qt、MFC、OWL、wxWidgets、WTL就是使用的C++。
欢迎关注我的微信公众号:九章算法(ninechapter),帮助你了解IT技术前沿,通过面试、拿到offer、找到好工作!
厨师都开始用Python和Java了?
学软件开发?那可不是闹着玩的。不从事这一行的永远不知道这行的艰辛,还咋巴着小眼睛问编程好不好学?
不知道LZ看没看过圣斗士星矢这部动漫,首先你得问问自己,想学编程,你有没有像星矢一样持之以恒百折不挠一步一个脚印忍受常人无法想象的困难和痛苦的品质,没有?你说我开玩笑逗你,那好,下面的不用看了,因为你确实不适合学。
如果你只想着挣大钱,劝你别碰这行,一句话,别来找虐。为什么?你看到的手机APP,各种应用,要想开发出来,不知道需要多少种技术。拿最常见的网站开发,需要后台数据库mysql,数据格式json,xml,各种网络协议,还有网站开发语言PHP, JSP,ASP.NET,等等不下十几种技术。而每一种技术都是一本厚厚的五六百页的书,需要最少一年多时间掌握一门技术。最要命的,每种技术互不交叉还跨度很大,每种技术都有自己的设计理念和很多很多“天坑”在等着你攻克,你问问你自己,你有这个恒心和意志力天天捧着本大部头的书天天看,天天上机操作学吗?你说有,那好,你看电视上那些富二代天天潇洒地到处游玩泡妞基本于你无缘了,因为你根本就没时间,谈个恋爱都困难,还想打网游玩王者?那算了,你还是别碰这行了,别耽误你玩游戏享受生活了。
程序员加班很恐怖,工作制通常是996,即早9晚9周六还要上班,晚9下班还是早的,一般到晚上十点。你想那时夜深人静了人家都休息抱着老婆孩子睡觉了,你还在工作中,是不是很崩溃?
第2,程序员耗脑太严重。工作中需要十几个小时大脑不停地运转。需要设计算法,不断地把代码改来改去来适应客户一天几变的需求。很多功能没有现成的解决方案,还经常遇到一些天书一样的疑难问题,bug,实际工作中突发状况千奇百怪,你可能见都没见过的bug,崩溃,需要一点一点查几万行的log日志。而且也需要百度,google,英文论坛寻求帮助,理解错误信息是什么意思。所以英文不好的没耐心的还是算了吧,不适合这行。
第3. 程序开发首先是非常难学的,任何一门编程语言都有自己独到的思想,概念设计,很多情况下一门语言与另一门语言没有多大关系,知识经验无法串用。而且工作中你还不得不用到这些技术你不得不去学。而且程序技术日新月异,新类库新SDK每天都会推出,你需要日复一日不断地学习新技术。如最新视频解码技术,游戏引擎等等,而这些新技术可是国内没有书和任何资料的,需要你到英文官方网站去找实例看文档去学,更要命的,新的技术和老的还没太大关联,你得重头去学。而且老板急赶项目不会给你什么时间,一般三天就是极限了,你需要这么短的时间快速掌握一项新技术...
综上,你明白程序员为什么总要加班了吧,也知道这行不是人干的吧。为什么说程序员干到三十干不动。很简单,以这种消磨人生所有时间状态,你生命中只有加班加班工作工作学习学习,你将不能顾家不能跟朋友聚会不能再有自己一点点休闲时间,更别说谈女朋友恋爱了,以这种状态你能坚持到三十岁?我想那简直是个奇迹了
初级java工程师可以做微信小程序吗?
首先介绍一下微信小程序宿主环境差异,其中iOS是基于JavaScriptCore,Android是基于X5内核,IDE是基于nwjs。小程序运行和加载机制小程序分为冷启动和热启动。而且小程序语言是数据绑定的,所以他的js并不能操作dome。但是实际应用中我们必不可少的需要改变一个元素的属性或css样式,这时就需要我们先在.wxnl文件中把需要更改的属性绑定一个变量{{变量}},然后我们需要在js的文件data里面给这个文件赋值就可以了,但是有的时候我们赋的值并不是死的,所以这时就需要我们不在data里面时运用this.setData({这里跟data是一样的})。如果要调用data里面的数据时可以用this.data.变量。
如果想自己开发一款个人小程序并且想上线发布,建议最好可以在开发之前就自己配置好域名、服务器,因为域名的备案可能会需要时间(审核会需要一些工作日),如果小程序完全都开发好了之后再购买域名服务器可能会浪费一点时间。