不经意之间的Bug(1):有些编译器可能在某些情况下无法识别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编译器的变量必须定义在域的开始的问题。

  • 14
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个数学不怎么好的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值