由func(i,++i)产生的问题

今天在看到C++程序设计(第四版)第89页的时候,书上这么说:

        例如,若变量i的值为3,有以下函数调用

func(i,++i)

如果按从左到右顺序求实参的值,则相当于func(3,4)       ps: 这句话没有什么问题

若按自右向左顺序求实参的值,则相当于func(3,3)

我按照教材上的思路走了一遍,因为i=3,所以++i 相当于将4的值传入,此时 i=4,然后再将4传入第一个参数的位置。最后的结果为func(4,4)。

“许多C++系统都是自右至左的顺序求值的”        所以,为了验证我的想法,我决定使用dev-C++ 进行实际操作。

#include <iostream>
using namespace std;
void func(int a,int b)
{
    cout<<"a = "<<a<<"\t&a = "<<&a<<endl;
	cout<<"b = "<<b<<"\t&b = "<<&b<<endl; 
}
int main()
{
    int i=3;
	func(i,++i);
	return 0;
}

 

运行结果和我所设想的一样 a 和 b 的值都为4,但是比较奇怪的是 a 和 b 之间多了四个字节的空档

访问该地址处的数据会得到一个-1的结果

事情到这里并没有完,我又尝试了其他几种情况,以func(++i,i)为例

#include <iostream>
using namespace std;
void func(int a,int b)
{
    cout<<"a = "<<a<<"\t&a = "<<&a<<endl;
	cout<<"b = "<<b<<"\t&b = "<<&b<<endl; 
}
int main()
{
    int i=3;
	func(++i,i);
	return 0;
}

最后运行结果

 这个结果多少出乎我的意料,按照之前的计算方法,最后结果应为func(4,3)才对

我又进行了几次尝试,发现参数的传入貌似并不是一个一个传入,传入之后就不再相互影响

以func(++i , i)为例,第二个参数位置一开始为3,但是到了第一个参数位置++i 的操作导致i的值变为4,此时第二个参数也会受到影响而变为4。最后出现func(4,4)的结果。

 

然后。。我又进行了新的尝试,我将 i 定义在全局区,出现了像我一开始想的那样的运行结果

#include <iostream>
using namespace std;
int i = 3;
void func(int a,int b)
{
    cout<<"a = "<<a<<"\t&a = "<<&a<<endl;
	cout<<"b = "<<b<<"\t&b = "<<&b<<endl; 
}
int main()
{
	func(++i,i);
	return 0;
}

 然后我访问了一下0x70fe04处的数据发现,此时该处的数据变成了0

到了这里,我就不能理解了,将此处留给以后研究吧。


总结规律:        ps:才疏学浅只能总结规律了,暂时给不出原理

将实参定义为局部变量时        func(++i,i)形式的传入有以下规律

1.从右至左的顺序求参数的值

2.参数计算完后并不会直接传入,会等待所有值计算完之后再传入,这一过程中会产生相互影响。

将实参定义为全局变量时

1.从右至左的顺序求参数的值

2.参数计算完之后直接传入,这一过程中不会产生相互影响

ps:教材一定是出错了

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
上传项目不支持Firefox,提示代码附件太大(1.4M),我写了30多分钟的描述全没了,太坑爹了。 10分有点贵,绝对原创,共2个代码文件300多行,下载请谨慎。你下载了,若绝对不爽在评论中说出来,不要让其他同学上当,如果觉得还可以也请留言。 代码采用多工作者多线程执行任务。通过暴露的方法往工作者传递消息,然后采用事件回调返回处理结果,实现的事件有OnThreadComplete,OnAddedTask,OnStart,OnSuccess,OnFailure,OnTimeout。 事件回调支持同步或异步,每工作者可以指定执行超时时间,避免线程阻塞死掉。队列采用线程安全的BlockingCollection,每组工作者用一个队列。委托采用Func来定义的,没有采用传统且不太好理解的Delegate。这让代码减少很多,也更容易理解。多线程应该采用消息中心来交换数据,这样就规避了线程同步交互,等待,阻塞等等,全部是异步调用,全部是接收消息工作,然后产生消息,线程间没有耦合,消息中心有很多成熟的方案如RabbitMQ, Redis(里面有简单的消息交换),微软有消息云服务等。如果应用不复杂,可以采用DB做个简单的消息中心,建议采用HTTP接口来获取与写入消息,方便将来升级重构消息中心。 开发环境VS2012,Framework4.0,代码注释量很大,如果你高兴这代码你可以随意蹂躏,如果你有建设性意见请告诉我。 下面是部分测试代码: //发送消息方法容器 var msgContainer = new Hashtable(); //创建并启动工作者 foreach (var key in workers.Keys) { //创建工作者 //启动5个线程,异步事件回调,方法执行20秒超时,程序跑起来有100个线程,由于引入超时控制,实际线程将达100+50 //下面的20个工作组,有5个是超时的,主要测试OnTimeout事件,你可以设置seleep的时间来控制 //我把sleep的时间设置的有点长,方便你测试 //测试的时候你会看见有异常,那是应为Timeout我采用的是Thread.Abort方法,这样才出发了ontimeout事件 var worker = new Sehui.Worker(5, key.ToString(), (Func)workers[key], false, new TimeSpan(0, 0, 20)); worker.OnStart += worker_OnEvent; worker.OnSuccess += worker_OnEvent; worker.OnFailure += worker_OnEvent; worker.OnTimeout += worker_OnEvent; //启动工作者 worker.Start(); //将增加消息方法放到Hashtable中 //这里我是偷懒,下面可以用循环的方式往线程中add message msgContainer.Add(key.ToString(), new Func(worker.AddTask)); } //向20个工作者发送消息,每个工作者发送20条消息 for (var i = 0; i < 20; i++) { for (var k = 0; k < 20; k++) { ((Func)msgContainer["SyncDb" + k])("[Work " + k + "] Message " + i); Console.WriteLine("send msg to worker{0},msgid:{1}", k, i); } }
previous up contents next C 语言常见问题集 原著:Steve Summit 翻译:朱群英, 孙 云 修订版 0.9.4, 2005年6月23日 版权所有 © 2005 * 目录 * 1. 前言 * 2. 声明和初始化 o 2.1 我如何决定使用那种整数类型? o 2.2 64 位机上的 64 位类型是什么样的? o 2.3 怎样定义和声明全局变量和函数最好? o 2.4 extern 在函数声明中是什么意思? o 2.5 关键字 auto 到底有什么用途? o 2.6 我似乎不能成功定义一个链表。我试过 typedef struct { char *item; NODEPTR next; } *NODEPTR; 但是编译器报了错误信息。难道在C语言中一个结构不能包含指向自己的指针吗? o 2.7 怎样建立和理解非常复杂的声明?例如定义一个包含 N 个指向返回指向字符的指针的函数的指针的数组? o 2.8 函数只定义了一次, 调用了一次, 但编译器提示非法重定义了。 o 2.9 main() 的正确定义是什么? void main() 正确吗? o 2.10 对于没有初始化的变量的初始可以作怎样的假定?如果一个全局变量初始为 ``零", 它可否作为空指针或浮点零? o 2.11 代码 int f() { char a[] = "Hello, world!";} 不能编译。 o 2.12 这样的初始化有什么问题?char *p = malloc(10); 编译器提示 ``非法初始式" 云云。 o 2.13 以下的初始化有什么区别?char a[] = "string literal"; char *p = "string literal"; 当我向 p[i] 赋的时候, 我的程序崩溃了。 o 2.14 我总算弄清除函数指针的声明方法了, 但怎样才能初始化呢? * 3. 结构、联合和枚举 o 3.1 声明 struct x1 { ...}; 和 typedef struct { ...} x2; 有什么不同? o 3.2 为什么 struct x { ...}; x thestruct; 不对? o 3.3 一个结构可以包含指向自己的指针吗? o 3.4 在 C 语言中实现抽象数据类型什么方法最好? o 3.5 在 C 中是否有模拟继承等面向对象程序设计特性的好方法? o 3.6 我遇到这样声明结构的代码: struct name { int namelen; char namestr[1];}; 然后又使用一些内存分配技巧使 namestr 数组用起来好像有多个元素。这样合法和可移植吗? o 3.7 是否有自动比较结构的方法? o 3.8 如何向接受结构参数的函数传入常数? o 3.9 怎样从/向数据文件读/写结构? o 3.10 我的编译器在结构中留下了空洞, 这导致空间浪费而且无法与外部数据文件进行 "二进制" 读写。能否关掉填充, 或者控制结构域的对齐方式? o 3.11 为什么 sizeof 返回的大于结构的期望, 是不是尾部有填充? o 3.12 如何确定域在结构中的字节偏移? o 3.13 怎样在运行时用名字访问结构中的域? o 3.14 程序运行正确, 但退出时却 ``core dump''了,怎么回事? o 3.15 可以初始化一个联合吗? o 3.16 枚举和一组预处理的 #define 有什么不同? o 3.17 有什么容易的显示枚举符号的方法? * 4. 表达式 o 4.1 为什么这样的代码: a[i] = i++; 不能工作? o 4.2 使用我的编译器,下面的代码 int i=7; printf("%d\n", i++ * i++); 返回 49?不管按什么顺序计算, 难道不该打印出56吗? o 4.3 对于代码 in

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值