quiz ; does this compile and if so what does it return (I know the answer)
I found this typo recently:
if (name.find('/' != string::npos))
O开发者_JAVA百科bviously the dev meant to type
if(name.find('/') != string::npos)
But I was amazed that to find that the error even compiles with -Wall -Werror
(didnt try with -pedantic
)
So, coffee quiz: does it evaluate to true or false?
'/' doesn't equal string::npos since npos is required to be negative, and none of the characters in the basic execution character set is allowed to be negative. Therefore, it's going to look for a value of 1
in the string (presumably a string anyway) represented by name
. That's a pretty unusual value to have in a string, so it's usually not going to find it, which means it'll return std::string::npos
, which will convert to true
.
Edit: as Johannes pointed out, although the value assigned to npos must be negative 1 (as per 21.3/6) that's being assigned to a size_type, which must be unsigned, so the result won't be negative. This wouldn't normally make any real difference though -- the '/' would be compared to npos
using unsigned arithmetic, so the only way they could have the same value would be if 1) '/' was encoded as -1 (not allowed as above) or char had the same range as size_type.
In theory, the standard allows char to have the same range as other integral types. In fact, quite a bit of I/O depends on EOF having a value that couldn't originate from the file, which basically translates to a requirement that char have a range that's smaller than int, not just smaller than or equal to (as the standard directly requires).
That does leave one loophole, though it's one that would generally be quite horrible: that char and short have the same range, size_type is the same as unsigned short, and int has a greater range than char/short. Giving char and short the same range wouldn't be all that horrible, but restricting size_type to the same range as short normally would be -- in a typical case, short is 16 bits, so it would restrict containers to 64K. That kind of restriction was problematic 20 years ago under MS-DOS; it simply wouldn't be accepted in most markets today.
It depends on if name
starts with a char
equal to 1.
You shouldn't be amazed it compiles, there's nothing wrong about it. '/' != std::string:npos
evaluates to true, and the only overload of find
that would work is the char c, size_t pos
version, as bool
can be converted to an integer 1.
So now we're looking for (char)1
, and what that returns depends on the string. If it starts with (char)1
, it returns 0 and that's false. In any other case, it returns a non-zero integer, or true.
'/' != string::npos evaluates to true. true is promoted to int (value = 1). find probably doesn't find a value of 1. if expression probably returns string::npos, which is typically -1, which is not zero, and is therefore true. My guess: true.
I'd say false, unless name contains a char with value 0x01.
I'm surprised the implicit cast from bool to char doesn't emit a warning... as far as I can tell, it'll return true unless name begins with '\001'.
It will evaluate to true if name contains a char == SOH
otherwise false
Others have posted the correct answer already: The result of the boolean expression should be 1 (a truth value), because '/'
should have a value smaller than the unsigned string::npos
(defined to be the largest value a size_t
can hold). Because 1 is an integer, and because 1 can't possibly be an address, the compiler finds the only overload of string::find()
it can call is the one with char c, size_t pos
.
But that's not the end of the story. Try to change the boolean expression from '/' != string::npos
to '/' == string::npos
. Now the result of the expression is 0, again an integer. Because there is no overload for string::find()
that takes an int
, the compiler must cast 0 -- but to what? It can cast it to a char
and it can cast it to a pointer. Both are valid choices, so that's an ambiguous call.
So there you go: your code changes from a valid warning-free function call to an ambiguous function call by changing an operator from !=
to ==
.
精彩评论