Any implicit else in a bracket less if-statement? Language unknown - if-statement

After getting in a discussion about the iOS Crypto Flaw also discussed on Ars Technica, someone mentioned that they encountered a case where, the line following a bracket-less if expression, was treated as an else.
if (<condition>)
<expression A>;
<expression B>;
<expression C>;
So, according to the person, expression B would be skipped if the condition was true, as if the else is implicit and unnecessary.
This in contrary to anything I've heard - my experience has been if the condition is true, then all three expressions would be executed - but seeing as I am a pro-bracket advocate, my experience may be limited, so I was hesitant to completely call the person out. Instead, I spent about 10 minutes clarifying and making sure I correctly understood what they were saying :)
Is there any truth in what they said? What language?
I'm pretty sure all major scripting languages follow my understanding. I think the person has a greater background in Objective-C. But if this is true, it could certainly be greatest reason to always use brackets.

That would be highly illogical and I strongly doubt any language with such syntax rules would gain much support (although the languages I choose to use all have syntax I'd prefer were different, so it's certainly possible).
Any possible way (I could think of) of implementing this would result in either seemingly inconsistent behaviour when looking at other syntax rules in the language, or very restricting in terms of what's possible, and, either way, initially detrimental to readability - if it has the same indentation, how would you then have an if-statement with multiple lines in its block, or would this be disallowed? If the else part would have reduced indentation instead, how would you differentiate between code that is part of the else, or code that is just after the if-statement, or must every if-statement have an else part? And multi-line else would also be a problem either way. If it's purely based on when there is or isn't curly braces or similar, this will just be really confusing to start.
That said, there's also esoteric languages, which is really has an "anything goes" motto.
An esoteric programming language (sometimes shortened to esolang) is a programming language designed to test the boundaries of computer programming language design, as a proof of concept, or as a joke.
I wouldn't be surprised, nor would it be particularly meaningful, if there were an esoteric language with such syntax rules.
An alternative is perhaps that the person was looking at a situation like this:
<type> someFunction()
{
if (<condition>)
return <expression A>;
return <expression B>;
}
This would be synonymous to an explicit else before the second return statement, as the return statement in the if-statement would cause the return statement following it to only be executed when the condition is false.

Related

Should I really massively introduce the explicit keyword?

When I used the (recently released) Cppcheck 1.69 on my code1, it showed a whole lot of messages where I expected none. Disabling noExplicitConstructor proved that all of them were of exactly this kind.
But I found that I'm not the only one with a lot of new Cppcheck messages, look at the results of the analysis of LibreOffice (which I'm allowed to show in public):
What would an experienced programmer do:
Suppress the check?
Massively introduce the explicit keyword?
1 This is of course not my code but code I have to work at work, it's legacy code: a mix of C and C++ in several (pre-)standard flavors (let's say C++98), and it's a pretty large code base.
I've been bitten in the past by performance hits introduced by implicit conversions as well as outright bugs. So I tend to always use explicit for all constructors that I do not want to participate in implicit conversions so that the compiler can help me catch my errors - and I then try to always also add a "// implicit intended" comment to the ctors where I explicitly intend for them to be used as converting ctors implicitly. I find that this helps me write more correct code with fewer surprises.
… So I'd say "yes, go add explicit" - in the long run you'll be glad you did - that's what I did when I first learned about it, and I'm glad I did.

Detecting "=" instead of "==" typo in if condition

Is there a way to make g++ yield a compilation error if I use = instead of == inside of an if condition in c++? I've made this typo a couple times, and it's annoying to track down. That is:
if (x=5){ //bad - sets x equal to 5
//do something
}
-Wparentheses option specifically warns such cases, which is also a part of -Wall option.
From gcc documentation:
-Wparentheses
Warn if parentheses are omitted in certain contexts, such as when there is an assignment in a context where a truth value is expected,
or when operators are nested whose precedence people often get
confused about.
...
When there is the potential for this confusion, GCC will issue a warning when this flag is specified. To eliminate the warning, add explicit braces around the innermost if statement so there is no way the else could belong to the enclosing if.
which can converted into an error using by specifying -Werror=parentheses.
Note that
if(x=5) {...}
is legal and standard requires no such diagnostics. But an implementation is allowed to provide any number of such useful warnings.
You can address this with a different coding style: a lot of programmers I know prefer to use the style if (5 == x) for this reason, because if you forget an equals sign then you get if (5 = x) which does not compile (5 is not an lvalue).
Aside from being a bit simpler than tinkering with compiler options, it is also portable to any standard C++ compiler.
IMO, the only downside is that it doesn't read as naturally if you're not used to it; in English it's more common to say "if x is equal to 5" instead of "if 5 is equal to x." Of course since equality is commutative, both are correct, but most people prefer the former. This is one of those cases where something that seems wrong from a stylistic perspective does help you write more maintainable code.
The Yoda condition is a simple, compiler independant solution: if (5=x){statement} will not compile.

How to use `return()` as expression?

|| is less verbose and easier to type than if (...), so I'd like a way to do the following (which happens a lot in my code):
int bar() {...; return successFlag;}
int foo() {
bar() || return(...); // return early on errors
...
}
Is it possible?
Or even better, is it possible to return back to main from bar, instead of chaining through foo?
For the first part, no: return is a keyword, not an expression, so it cannot combined in that form. I think you are instinctively reading || literally as meaning "or" in the English language sense - obviously that's not what it means.
For the second part, you could - in theory - by using exceptions, but it is a strongly discouraged practice. Exceptions are intended for "exceptional circumstances", more specifically, error conditions from which the code cannot recover locally (in the context of the current function/method) and where the proper action has to be determined at a higher level.
Use of exceptions as a general flow control mechanism has two problems:
Performance: C++ compilers are optimized for "non-exceptional" code paths (because that's what should be happening normally) and so exception handling mechanisms tend to be very slow. This is not from lack of code optimization, but from the need of the mechanism to have a zero or near-zero cost if there are no exceptions, even if the cost is for exceptions to take a lot of work to process.
code clarity/testability: using exceptions for control flow makes code immensely hard to read and unit-test properly in isolation.
For the first part - NO. For the second: setjmp and longjmp. But take note that both of them subvert the usual C++ stack based destructor calls and probably don't mix well with exceptions.

Expressions with no side effects in C++

See, what I don't get is, why should programs like the following be legal?
int main()
{
static const int i = 0;
i < i > i;
}
I mean, surely, nobody actually has any current programs that have expressions with no side effects in them, since that would be very pointless, and it would make parsing & compiling the language much easier. So why not just disallow them? What benefit does the language actually gain from allowing this kind of syntax?
Another example being like this:
int main() {
static const int i = 0;
int x = (i);
}
What is the actual benefit of such statements?
And things like the most vexing parse. Does anybody, ever, declare functions in the middle of other functions? I mean, we got rid of things like implicit function declaration, and things like that. Why not just get rid of them for C++0x?
Probably because banning then would make the specification more complex, which would make compilers more complex.
it would make parsing & compiling the
language much easier
I don't see how. Why is it easier to parse and compile i < i > i if you're required to issue a diagnostic, than it is to parse it if you're allowed to do anything you damn well please provided that the emitted code has no side-effects?
The Java compiler forbids unreachable code (as opposed to code with no effect), which is a mixed blessing for the programmer, and requires a little bit of extra work from the compiler than what a C++ compiler is actually required to do (basic block dependency analysis). Should C++ forbid unreachable code? Probably not. Even though C++ compilers certainly do enough optimization to identify unreachable basic blocks, in some cases they may do too much. Should if (foo) { ...} be an illegal unreachable block if foo is a false compile-time constant? What if it's not a compile-time constant, but the optimizer has figured out how to calculate the value, should it be legal and the compiler has to realise that the reason it's removing it is implementation-specific, so as not to give an error? More special cases.
nobody actually has any current
programs that have expressions with no
side effects in them
Loads. For example, if NDEBUG is true, then assert expands to a void expression with no effect. So that's yet more special cases needed in the compiler to permit some useless expressions, but not others.
The rationale, I believe, is that if it expanded to nothing then (a) compilers would end up throwing warnings for things like if (foo) assert(bar);, and (b) code like this would be legal in release but not in debug, which is just confusing:
assert(foo) // oops, forgot the semi-colon
foo.bar();
things like the most vexing parse
That's why it's called "vexing". It's a backward-compatibility issue really. If C++ now changed the meaning of those vexing parses, the meaning of existing code would change. Not much existing code, as you point out, but the C++ committee takes a fairly strong line on backward compatibility. If you want a language that changes every five minutes, use Perl ;-)
Anyway, it's too late now. Even if we had some great insight that the C++0x committee had missed, why some feature should be removed or incompatibly changed, they aren't going to break anything in the FCD unless the FCD is definitively in error.
Note that for all of your suggestions, any compiler could issue a warning for them (actually, I don't understand what your problem is with the second example, but certainly for useless expressions and for vexing parses in function bodies). If you're right that nobody does it deliberately, the warnings would cause no harm. If you're wrong that nobody does it deliberately, your stated case for removing them is incorrect. Warnings in popular compilers could pave the way for removing a feature, especially since the standard is authored largely by compiler-writers. The fact that we don't always get warnings for these things suggests to me that there's more to it than you think.
It's convenient sometimes to put useless statements into a program and compile it just to make sure they're legal - e.g. that the types involve can be resolved/matched etc.
Especially in generated code (macros as well as more elaborate external mechanisms, templates where Policies or types may introduce meaningless expansions in some no-op cases), having less special uncompilable cases to avoid keeps things simpler
There may be some temporarily commented code that removes the meaningful usage of a variable, but it could be a pain to have to similarly identify and comment all the variables that aren't used elsewhere.
While in your examples you show the variables being "int" immediately above the pointless usage, in practice the types may be much more complicated (e.g. operator<()) and whether the operations have side effects may even be unknown to the compiler (e.g. out-of-line functions), so any benefit's limited to simpler cases.
C++ needs a good reason to break backwards (and retained C) compatibility.
Why should doing nothing be treated as a special case? Furthermore, whilst the above cases are easy to spot, one could imagine far more complicated programs where it's not so easy to identify that there are no side effects.
As an iteration of the C++ standard, C++0x have to be backward compatible. Nobody can assert that the statements you wrote does not exist in some piece of critical software written/owned by, say, NASA or DoD.
Anyway regarding your very first example, the parser cannot assert that i is a static constant expression, and that i < i > i is a useless expression -- e.g. if i is a templated type, i < i > i is an "invalid variable declaration", not a "useless computation", and still not a parse error.
Maybe the operator was overloaded to have side effects like cout<<i; This is the reason why they cannot be removed now. On the other hand C# forbids non-assignment or method calls expresions to be used as statements and I believe this is a good thing as it makes the code more clear and semantically correct. However C# had the opportunity to forbid this from the very beginning which C++ does not.
Expressions with no side effects can turn up more often than you think in templated and macro code. If you've ever declared std::vector<int>, you've instantiated template code with no side effects. std::vector must destruct all its elements when releasing itself, in case you stored a class for type T. This requires, at some point, a statement similar to ptr->~T(); to invoke the destructor. int has no destructor though, so the call has no side effects and will be removed entirely by the optimizer. It's also likely it will be inside a loop, then the entire loop has no side effects, so the entire loop is removed by the optimizer.
So if you disallowed expressions with no side effects, std::vector<int> wouldn't work, for one.
Another common case is assert(a == b). In release builds you want these asserts to disappear - but you can't re-define them as an empty macro, otherwise statements like if (x) assert(a == b); suddenly put the next statement in to the if statement - a disaster! In this case assert(x) can be redefined as ((void)0), which is a statement that has no side effects. Now the if statement works correctly in release builds too - it just does nothing.
These are just two common cases. There are many more you probably don't know about. So, while expressions with no side effects seem redundant, they're actually functionally important. An optimizer will remove them entirely so there's no performance impact, too.

Brackets around 0 in "return (0);" statement in 'main' function - what are they for? [duplicate]

This question already has answers here:
When do extra parentheses have an effect, other than on operator precedence?
(2 answers)
Closed 3 years ago.
Usually auto-generated c++ "main" function has at the end
return (0);
or
return (EXIT_SUCCESS);
But why there are parentheses in above statements? Is it related to C language or something?
// EDIT
I know this is correct, but someone put these brackets for a reason. What's the reason?!
They are not required (even in c). I think some people use them to make 'return' look more like a function call, thinking it is more consistent.
Edit: It's likely the generator does this for it's own reasons. It may be safer or easier for it to work this way.
But why there are parentheses in above
statements? Is it related to C
language or something?
No. As far as I can tell, C has never required parentheses for return statements. This appears to have been the case even before the first ANSI C standard.
This is actually a very interesting question, however, as I've seen that style prevalent among certain C programmers.
I think the most likely guess as to why this style came about is because all other branching statements (for, while, if, switch) require parentheses around expressions. People might have been unaware that they could omit the parentheses for return statements or were aware of this but wanted to achieve a more uniform look to their code.
The ternary ?: operator is sort of an exception as it is an operator and doesn't require parentheses around the conditional expression, yet people often write parentheses there as well regardless of whether it's needed. Some might find it serves to 'group' an expression into a single unit visually.
My second best guess is that this style was influenced by other languages popular at the time. However, popular, procedural alternatives at the time like Pascal did not require that syntax either (Pascal did not even have return values in the C sense but only output parameters) so if this is the case, I'm not aware of any particularly language from which this style originated.
[Subjective] I prefer styles that require the least amount of superfluous decoration to the code whether it comes to naming conventions or how to format it or whether to use additional parentheses where unnecessary. I find that any such decoration tends to be a matter of unique personal preference and falling in love with one way of decorating code just means that someday you'll have to deal with a completely different way (unless you work strictly alone, in which case I envy you). [/Subjective]
This is actually a requirement for BSD kernel source file style.
man 9 style says:
Space after keywords (if, while, for, return, switch).
and
Values in return statements should be enclosed in parentheses.
As any valid expression can be passed to return, those brackets can be added if desired. It is like doing this:
int i = (0);
You can nest an expression in as many brackets as you like:
return (((((0)))));
Things changes with the use of decltype(auto) in c++14 to deduce return type. If parentheses are used then returned type is deduced to be a reference:
decltype(auto) foo1() {
int n;
return (n); // parentheses causes return type to be int&
}
decltype(auto) foo2() {
int n;
return n; // no parentheses causes return type to be int
}
template<typename T> struct TD;
int main()
{
// main.cpp:19:22: error: aggregate 'TD<int&()> f1' has incomplete type and cannot be defined TD<decltype(foo1)> f1;
TD<decltype(foo1)> f1;
// main.cpp:20:22: error: aggregate 'TD<int()> f2' has incomplete type and cannot be defined TD<decltype(foo2)> f2;
TD<decltype(foo2)> f2;
}
There's a dumb reason - to make return look more like a function call.
There's a smarter reason - if the code is generated, code generators often "play it safe" by putting parentheses around expressions just so they never have to be concerned about the precedence leaking out.
Just my silly speculation:
#define RETURN(val) { if (val) printf("Main Exit With Error %d\n", val); return val; }
int main(argc, argv)
{
...
RETURN (E_FILENOTFOUND);
}
Those are not required. Maybe they come from the tendency to prefer more brackets to fewer brackets when writing macros.
Since you mention auto-generated code it might happen that the code used for generating macros was written by reusing code for generating macros or by a person who thought that more brackets won't hurt, but fewer brackets can be fatal.
One reason I can see for this:
return (ERROR_SUCCESS);
is that it's expressing the concept that ERROR_SUCCESS is opaque. We all know it's 0L, but we shouldn't have to.
That's a fairly weak reason.
Another is that it's aesthetically pleasing to use parentheses for consistency, another weak reason.
So in other words, I don't use it myself, but wouldn't flip out if someone else did. :)