我最近发现了这个错字:
if (name.find('/' != string::npos))
显然,开发者打算输入
if(name.find('/') != string::npos)
但我惊讶地发现错误甚至与-Wall -Werror
编译(没有尝试使用-pedantic
)
所以,咖啡测验:是评估为真还是假?
答案 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
并且可以将其转换为指针。两者都是有效的选择,所以这是一个模棱两可的选择。
所以你去了:你的代码从有效的无警告函数调用变为模糊函数调用,方法是将操作符从!=
更改为==
。