Obfuscated C++
- By Rob Murray
- February 24, 2000
Last Month's Obfuscated C++
Last month we asked you to suggest a declaration or definition that will allow the following code fragment to compile and print "Success":
//What declaration of x?
if (x == &x) cout < "success\n";="">
Declaring x as something like an int* won't work, because &x will always have a different type than x. Comparison of two different pointer types for equality is not legal without casting one pointer to the type of the other (preferably by using reinterpret_cast). The solution to this puzzle can be found in the treatment of function names in section 4.3 of the ISO C++ standard:
"An lvalue of function type T can be converted to an rvalue of type 'pointer to T'. The result is a pointer to the function."
The practical effect of this is that the unqualified name of a function-without any parentheses or arguments-can be used as a synonym for its address. This means that the expressions x and &x are both legal rvalues, and are in fact synonyms, if x is the name of a function:
void x();
if (x == &x) cout < "success\n";="">
|
This Month's Obfuscated C++
This month we abuse exceptions. Explain the semantics of function f in the following code:
static void
g(unsigned long x) {
if (!x) throw 0;
if (x&1) {
try {g(x>>1);} catch (int x) {
throw x+1;
}
}
g(x>>1);
}
int
f(unsigned long l) {
try {
g(l);
} catch (int l) {
return l;
}
return 6;
}
Rob Murray is Director of Operations at the Irvine office of Nuforia, an object-oriented software consulting company based in Houston, TX. He has taught C++ at technical conferences since 1987 and is the author of
C++ Strategies and Tactics. He was the founding editor of
C++ Report and may be contacted at
[email protected].