测验;这会编译,如果是这样,它返回什么(我知道答案)

时间:2010-03-23 22:49:28

标签: c++

我最近发现了这个错字:

 if (name.find('/' != string::npos))

显然,开发者打算输入

if(name.find('/') != string::npos)

但我惊讶地发现错误甚至与-Wall -Werror编译(没有尝试使用-pedantic

所以,咖啡测验:是评估为真还是假?

7 个答案:

答案 0 :(得分:3)

'/'不等于string :: npos,因为npos必须为负数,并且基本执行字符集中的所有字符都不允许为负数。因此,它将在1表示的字符串中查找name的值(可能是一个字符串)。这在字符串中是非常不寻常的值,因此它通常不会找到它,这意味着它将返回std::string::npos,它将转换为true

编辑:正如Johannes指出的那样,虽然分配给npos的值必须是负1(按照21.3 / 6),它被分配给size_type,而size_type必须是无符号的,因此结果不会是负数。这通常不会产生任何真正的差别 - 使用无符号算术将'/'与npos进行比较,因此它们具有相同值的唯一方法是1)'/'被编码为-1(不允许如上)或char与size_type具有相同的范围。

理论上,该标准允许char与其他整数类型具有相同的范围。实际上,相当多的I / O依赖于EOF具有不能源自文件的值,这基本上转换为char的范围小于而不是int的要求,而不仅仅是小于或等于(标准直接要求)。

这确实留下了一个漏洞,尽管它通常是非常可怕的:char和short具有相同的范围,size_type与unsigned short相同,int的范围大于char / short。赋予char和缩短相同的范围并不是那么可怕,但是将size_type限制为与通常短的相同范围 - 在典型情况下,short是16位,因此它将容器限制为64K。 20年前在MS-DOS下,这种限制是有问题的;它在今天的大多数市场都不会被接受。

答案 1 :(得分:1)

这取决于name 启动char等于1。

你不应该惊讶它编译,它没有错。 '/' != std::string:npos的计算结果为true,find唯一可用的重载是char c, size_t pos版本,因为bool可以转换为整数1。

所以现在我们正在寻找(char)1,返回的内容取决于字符串。如果它以(char)1开头,则返回0并且为false。在任何其他情况下,它返回一个非零整数,或者为真。

答案 2 :(得分:1)

'/'!= string :: npos计算结果为true。 true被提升为int(value = 1)。 find可能找不到值1.如果expression可能返回string :: npos,它通常是-1,它不是零,因此是真的。我的猜测:是的。

答案 3 :(得分:0)

我会说false,除非name包含值为0x01的char。

答案 4 :(得分:0)

我很惊讶从bool到char的隐式演员不会发出警告......据我所知,除非名字以'\ 001'开头,否则它将返回true。

答案 5 :(得分:0)

如果name包含char == SOH

,它将评估为true

否则为假

答案 6 :(得分:0)

其他人已经发布了正确答案:布尔表达式的结果应为1(真值),因为'/'的值应小于无符号string::npos(定义为size_t可以容纳的最大值。因为1是一个整数,并且因为1不可能是一个地址,所以编译器发现它可以调用string::find()的唯一重载是具有char c, size_t pos的那个。

但这不是故事的结局。尝试将布尔表达式从'/' != string::npos更改为'/' == string::npos。现在表达式的结果是0,再次是整数。因为string::find()没有带int的重载,编译器必须转换为0 - 但是对于什么?它可以将它转换为char并且可以将其转换为指针。两者都是有效的选择,所以这是一个模棱两可的选择。

所以你去了:你的代码从有效的无警告函数调用变为模糊函数调用,方法是将操作符从!=更改为==