不同编译器对于等号左右两侧执行顺序及简单IO优化


最近写作业遇到的一个问题,花了两天时间才解决。

问题背景是平衡树的插入和删除,为了方便就直接拿老师示例代码进行更改。在线下自己测试都没问题,但是提交到线上就会出现内存访问错误(exitcode11),自己写了一个生成算例的小程序进行测试还是没有问题。后来经助教提示,选择与线上测试更接近的编译器。之前环境是Win8+VS2012,后来在Win7+Dev-cpp 4.9.9.2上测试,终于重现出问题。经过对不同模块的测试,最终将错误代码定位到其中一行:

FromParentTo ( *g ) = rotateAt ( tallerChild ( tallerChild ( g ) ) ); //为了能够使父节点正常地指向旋转后的子节点

其中左侧为一个宏,定义为:

#define FromParentTo(x) /*来自父亲的引用*/ \
   ( IsRoot(x) ? this->_root : ( IsLChild(x) ? (x).parent->lc : (x).parent->rc ) )

经测试发现在dev-cpp下,这行代码会出问题,经过变换后树的结构变化并不正确。而在VS下无这个问题。

当时就在想出错的原因是否是因为等是两侧执行的顺序不同而导致的,后来有点困了,就先停下来了。第二天助教回邮件也说道可能是这个问题。于是将这句话改为:

if (!g->parent)
	this->_root = rotateAt ( tallerChild ( tallerChild ( g ) ) );
else if (IsLChild(*g))
 {
	BinNodePosi(T) p = g->parent;
	 p->lc = rotateAt ( tallerChild ( tallerChild ( g ) ) );
 }
 else
 {
	 BinNodePosi(T) p = g->parent;
	 p->rc = rotateAt ( tallerChild ( tallerChild ( g ) ) );
 }


困扰两天的问题终于解决!也验证了猜想,即由于在Dev-cpp中,先执行等式右侧代码,而导致树的结构发生变化,再执行等式左侧得到的结果已经不是从之前节点g来自父节点的引用。而在VS下结果相反,因此并未代码并没有出问题。

此外,最后提交代码时超时,最终经提醒采用了增加缓冲区大小的方式来减少IO读取次数,从而提高读取速度,具体代码如下:

char inBuf [100000]; 
setvbuf(stdin, inBuf, _IOFBF, 100000);
之后正常使用scanf,printf等。

总结一下:

1.Dev-cpp编译器会先执行等式右侧表达式再执行左侧,而VS则相反。

2.尽量减少长代码,不仅影响阅读,还容易出错。

3.使用setvbuf可以在一定程度上提高读取速度。


你可能感兴趣的:(c/c++)