不经意之间的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定义的标识符的主要内容,如果未能解决你的问题,请参考以下文章