跟我快乐学C++系列:(4)理解函数的调用
来源:互联网 发布:血清甘油三酯增高 知乎 编辑:程序博客网 时间:2024/05/28 16:25
跟我快乐学C++系列:(4) 理解函数的调用
引言
本节课我们依然通过C++代码来探索C++函数。通过分析本节课提供的代码,观察程序的执行结果,您可以发现C++函数调用时形参,实参之间有趣的现象,理解这些现象的本质将有助于理解指针。
适用对象:
本文仅用于初学C++的同学。
如果您对本文理解困难,可以参考本系统的前面的课程:
第一节:介绍了安装c++开发环境,通过图解,您可以获得一个g++的开发环境;
第二节:介绍了c++的基本程序结构;
第三节:介绍了指针的初步。
另外,您还可以参考《跟我学“数据结构”》的第一节。
C++函数调用
C++语言通过函数可以把一系列的语句包装在一起被其它函数调用,这相当于把函数的中的语句插入到调用它的代码中一样。
理解函数要理解几个重要的术语:
l 函数的名称
l 函数的参数列表
l 函数的返回值类型
l 函数的返回值
l 函数的原型
l 形式参数
l 实际参数
不用担心上面的术语太多,我们通过示例,就能更好的理解它们。
函数 int main (int argc, char* argv[])
上面这个函数大家最熟悉了。它的函数
名称
main
参数列表
int argc, char* argv[]
两个参数,一个是argc,另一个是argv
反回值的类型
int
返回值
在函数结果的 return 0; 0表示是这个函数的返回值。调用main是操作系统,操作系统处理这个返回值。对于操作系统而言,通常0表示函数成功结束。非0表示失败结束。
函数原型
返回类型,名称,参数列表合在一起叫函数原型
形式参数
在函数参数列表中的参数名。
这里argc, argv就是形式参数
实际参数
调用时使用的参数。(后面再举例讲解)
运行本节的代码并观察结果
为了讲解方便,代码的运行结果中我们使用了行号,因此建议在编辑器中打开显示行号的功能。
[代码]
- #include <iostream>
- #include<iomanip>
- #include<string>
- using namespace std;
- void showBytes(unsigned char* p, size_t length);
- template <typename T> void showType( T x);
- void showPointerAddress(string name,const void* p);
- void add_100(int* x, int* p);
- void add_100_2(int& x, int *p);
- void bad_add_100(int x,int *p);
- int main(int argc, char* argv[])
- {
- int a = 3;
- int* p = &a;
- cout << "line 18:" << " a = " << dec << a << endl;
- showPointerAddress("line 19 a's address = ",p);
- add_100(&a,p);
- cout << "line 21:" << " a = " << dec << a << endl;
- cout << "line 23:" << " the value in addrees p is " << dec << *p << endl;
- a = 3;
- cout << "line 24: let a is 3" << " a = " << dec << a << endl;
- showPointerAddress("line 25 a's address = ",p);
- bad_add_100(a,p);
- cout << "line 28:" << " a = " << dec << a << endl;
- cout << "line 29:we can not change the a's value. :( " << endl;
- a = 3;
- cout << "line 30: let a is 3" << " a = " << dec << a << endl;
- add_100_2(a,p);
- cout << "line 32:" << " a = " << dec << a << endl;
- return 0;
- }
- void add_100(int* x,int *p)
- {
- *x = *x + 100;
- showPointerAddress("/tline 39 x's address = ",x);
- cout << "/tline 40, p's address is same as x." << endl;
- cout << "/tline 41:" << " the value in addrees p is " << dec << *p << endl;
- }
- void bad_add_100(int x,int *p)
- {
- x = x + 100;
- showPointerAddress("/tline 46 x's address = ",&x);
- cout << "/tline 47, p's address is NOT same as x." << endl;
- cout << "/tline 48:" << " the value in addrees p is " << dec << *p << endl;
- }
- void add_100_2(int& x, int *p)
- {
- x = x + 100;
- showPointerAddress("/tline 55 x's address = ",&x);
- cout << "/tline 56, p's address is same as x." << endl;
- cout << "/tline 57:" << " the value in addrees p is " << dec << *p << endl;
- }
- void showBytes(unsigned char* p, size_t length)
- {
- unsigned int i = 0;
- for(i = 0; i < length ; i++)
- {
- //printf(" %.2x",p[i]);
- cout<<hex<<setw(2)<<right<<setfill('0')<<(int)p[i] << " ";
- }
- cout << endl;
- }
- template < typename T > void showType(T x)
- {
- showBytes((unsigned char* )&x, sizeof (T));
- }
- void showPointerAddress(string name,const void* p)
- {
- cout << name << " ";
- showType<const void*>(p);
- }
line 18: a = 3
line 19 a's address = 60 ff 12 00
line 39 x's address = 60 ff 12 00
line 40, p's address is same as x.
line 41: the value in addrees p is 103
line 21: a = 103
line 23: the value in addrees p is 103
line 24: let a is 3 a = 3
line 25 a's address = 60 ff 12 00
line 46 x's address = 34 ff 12 00
line 47, p's address is NOT same as x.
line 48: the value in addrees p is 3
line 28: a = 3
line 29:we can not change the a's value. :(
line 30: let a is 3 a = 3
line 55 x's address = 60 ff 12 00
line 56, p's address is same as x.
line 57: the value in addrees p is 103
line 32: a = 103
代码讲解
帮助函数
代码中使用了3个帮助函数:
void showBytes(unsigned char* p, size_t length);
template <typename T> void showType( T x);
void showPointerAddress(string name,const void* p);
这些函数用来显示地址的值。我们不是第一次使用这类帮助函数了,在“跟我学数据结构”一节中,我们也使用了类似的技巧能帮助我们理解c++的机制。
代码要点
我们先显示出为变量a的值的地址。请注意代码的第20行,调用 void add_100(int* x, int *p)。调用的代码是第20行。这里的代码
add_100(&a , p),其中 a, p表示函数的实际参数。我们再看代码的36行,这里是函数的实现(即函数的定义),这里的在数列表中的x, p叫形式参数。我们可以让实参与形参用同一个标识符(如p)也可以用不同的标识符如(a,x)。
当我们以指针(地址)为参数调用的函数add_100(),我们得到了期望的结果。
紧接着我们试用以传值的方式调用函数bad_add_100(),我们发现形参与实参的地址并不相同,也就是,我们试图修改的值a与实际修改的值x并不是同一个变量,所以我们得不到想要的结果。
C++和C语言相比增加了引用类型,它相当于给变量取了一个别名,与指针非常相似,在某些场合要可以代替指针。我们的函数void add_100_2(int& x, int *p)就演示了这个用法。我们发现,引用的地址实际上与实参的地址相同,所以我们得到了期望的结果。
- 跟我快乐学C++系列:(4)理解函数的调用
- 跟我学Python系列 -Map()函数的理解
- 跟我学TCP/IP系列4
- 系统调用跟我学(1-4)
- 系统调用跟我学(4)
- 系统调用跟我学(4)
- 系统调用跟我学之wait, waitpid函数
- 系统调用跟我学
- 系统调用跟我学
- 系统调用跟我学
- 系统调用跟我学
- 《跟我一起学C++》
- 跟我一起学OC系列-OOP编程的基础知识
- 跟我一起学算法系列4---替换空格
- 《跟我一起学Makefile》之函数的使用
- 《跟我学Shiro》系列教程
- 跟我学Spring系列链接
- 跟我学Java安全编程系列
- 二叉树问题
- 开源工作的参与是不是可以从测试开始?
- “晨曦计划”我的第一讲
- 个人主页
- 这地方不错~
- 跟我快乐学C++系列:(4)理解函数的调用
- JefferyZhao教导我们...
- 为啥这没个动态语言的讨论区,比如Python
- 一道简单的关于override的测试题
- 实验四、4哈夫曼树编码
- 在网上发现了一篇关于接口的文章拿来分享一下
- 提供Cygwin国内镜像的链接地址
- Head Frist JavaScript(中文版)第一章翻译完毕
- 文件上传的原理