不经意之间的Bug:有些编译器可能在某些情况下无法识别typedef定义的标识符

Posted 变秃变强 呀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不经意之间的Bug:有些编译器可能在某些情况下无法识别typedef定义的标识符相关的知识,希望对你有一定的参考价值。

如何发现这个bug的

在前几天在写一个问题的代码:找二叉树中值为x的结点,并返回。下面来看看当时写的代码。

BT* BinaryTreeFind(BT* root,BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->x == x)
		return root;
    BT* ansleft = BinaryTreeFind(root->left, x);
	if (ansleft)
	{
		return ansleft;
	}
	BT* ansright = BinaryTreeFind(root->right, x);
	if (ansright)
	{
		return ansright;
	}
	return NULL;
}

可能很多人看这段代码并没有什么问题,甚至在有些编译器上还能编译过去。确实,这段代码我一开始写完也觉得没什么问题,可是运行之后总是会报这个错误。

这就让人感觉很疑惑了,我不是定义了ansleft了吗,为什么会说我没有定义了?而且为什么会报错误1了,BT将此类型用作表达式非法。然后到csdn上去查了下,其实错误1是由于c的编译器要求将变量的申明放在一个函数块的头部。
那意思就是我的ansleft没有定义在函数块的开头?这时你又要疑惑了,前面的是if语句啊,其实也就相当于把ansleft定义在域的开头了,为了验证这个,我还特地测试了一下

那么问题出哪儿了?其实这是编译器的一个bug,在某些情况下,编译器无法识别typedef定义的标识符。下面我们来看看例子。
此时编译器可以识别出typedef定义的标识符。

触发编译器无法识别typedef的条件

这里有个注意点:要触发这个报错,那个if千万不能加{},虽说if后面只有一句代码,可加可不加,但是如果你想要编译器无法识别出的话,就不要加{},因为你不加{},编译器就不会把if后面的那块当成域的开始,如果你加{}的话,编译器就会把它后面的那块当成域的开始。这其实也就是一开始那个问题为什么会报错的原因。

解决方法

用原生类型

既然此时typedef无法识别出你typedef出来的量,那我们不防用它的原生类型,这样总能识别出来吧。

果真不出我们所料,编译器此时是可以识别出来的。

if哪怕只有一句话时也加上括号

这种方法其实就是之前提到的,if如果不加{}的话,编译器在某些情况下不会把后面那块当成域的开始。那我们就加上{}呗,毕竟这也是一个书写的好习惯。

可以看到,此时也很顺利的编译过去了。

把所要用的变量定义在函数块的最前面

既然if没有加{}在某些情况下,后面的那块不会被当时域的开始,那我们不防就写在函数块的最前面,这样肯定就是域的开始了吧。

这样也可以编译过去。

总结

其实这个问题也不能完全归纳为:有些编译器可能在某些情况下无法识别typedef定义的标识符。这里面其实也有:c编译器的变量必须定义在域的开始的问题。

以上是关于不经意之间的Bug:有些编译器可能在某些情况下无法识别typedef定义的标识符的主要内容,如果未能解决你的问题,请参考以下文章

pycharm编译乘法计算问题?

编译器 bug 系列

当你的系统依赖于某个bug...

发布和调试之间的 ABI 兼容性

对UVCCamera的改进----解决某些设备无法识别摄像头等bug

对UVCCamera的改进----解决某些设备无法识别摄像头等bug