Ill formed code snippets - c++

can somebody please tell me the difference between the following two code snippets:
//Code snippet A: Compiles fine
int main()
{
if(int i = 2)
{
i = 2 + 3;
}
else
{
i = 0;
}
}
//Code Snippet B: Doesn't compile :(
int main()
{
if((int i = 2))
{
i = 2 + 3;
}
else
{
i = 0;
}
}
If you notice the diff is just an extra parenthesis at if statement. I am using g++ compiler.Error is "expected primary-expression before âintâ"

Section 6.4 of the C++ standard (draft n2914 of c++0x) has this to say about the format of if statements:
Selection statements choose one of several flows of control.
selection-statement:
if ( condition ) statement
if ( condition ) statement else statement
switch ( condition ) statement
condition:
expression
type-specifier-seq attribute-specifieropt declarator = initializer-clause
type-specifier-seq attribute-specifieropt declarator braced-init-list
That bit at the end means a condition can be either an expression or a decalarator-type construct.
And the minute the parser hits that second parenthesis, it becomes an expression, so no declarations allowed, I'm afraid.
The snippet:
if (int i = 2) { ... } else { ... }
is perfectly valid C++ in which the if section defines an integer i for the duration of the if/else and sets it to 2. It then uses that 2 as the input to the if (2 is always true, being non-zero).
The snippet if((int i = 2)) is no different syntactically to int x = (int i = 2;); if (x) which is not valid C++.

Snippet A is fine - the if condition delares and initialises a variable that can be interpreted as a boolean. The variable is defined within the if and any else blocks.
Snippet B is wrong, because you can't put parentheses around a declaration - you can only put them round expressions. The following is also wrong for the same reason:
int main()
{
int i; // OK
(i = 2); // OK
(int x = 2); // compile error
}

Here is another variant of second snippet error:
int main()
{
int i = (int j = 0);
return 0;
}
You can't declare variables inside ANY expression.
Second () inside for is the same case - you can declare variable i inside for() but not inside nested expression placed into ().
Hope I explained it in proper words, maybe more correct explanation exists. Actually both code fragments are odd.

Both look wrong.
Just because code compiles it doesn't mean it's valid. I'm surprised that the first case is compiling, since it seems like i isn't defined in the else case.
edit: I'm wrong here, definitions in the if condition are valid for that whole if / else statement.

Related

Multiline Formatting of else Statements in C/C++ without Braces

I am rewriting some C++ code, I have the following
if (ConfidenceBias.value > 0) *normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionAndBiasFunction);
else *normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionFunction); ThreadPool::Parallel_for(0, normalInfo->size(), [&](unsigned int, size_t i) { (*normalInfo)[i] *= (Real)-1.; });
I assume that this is equivalent to
if (ConfidenceBias.value > 0)
{
*normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionAndBiasFunction);
}
else
{
*normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionFunction);
}
ThreadPool::Parallel_for(0, normalInfo->size(), [&](unsigned int, size_t i) { (*normalInfo)[i] *= (Real)-1.; });
but there is a slight conern that the compiler is interpreting the original as
if (ConfidenceBias.value > 0)
{
*normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionAndBiasFunction);
}
else
{
*normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionFunction);
ThreadPool::Parallel_for(0, normalInfo->size(), [&](unsigned int, size_t i) { (*normalInfo)[i] *= (Real)-1.; });
}
I cannot find a reference to what the VSVC compiler does anywhere. Which is it?
AFAIK your assumption about the code is correct.
For most languages I am ware of only one statement or a compound-statement (e.g. braces) will be executed on the condition.
The
ThreadPool::Parallel_for(0, normalInfo->size(), [&](unsigned int, size_t i) { (*normalInfo)[i] *= (Real)-1.; });
line is really really oddly hidden after the condition and I would assume this a code smell because it makes code hard to read, understand and debug.
Edit because I like complete answers: Also you actually do not need to know what VS C++ compiler is going to do here because this is defined. See Alex Allain's post about this.
Refer to the MSDN docs for this as well: https://learn.microsoft.com/en-US/cpp/cpp/statements-cpp?view=vs-2019
https://learn.microsoft.com/en-US/cpp/cpp/if-else-statement-cpp?view=vs-2019
states
Controls conditional branching. Statements in the if-block are
executed only if the if-expression evaluates to a non-zero value (or
TRUE). If the value of expression is nonzero, statement1 and any other
statements in the block are executed and the else-block, if present,
is skipped. If the value of expression is zero, then the if-block is
skipped and the else-block, if present, is executed. Expressions that
...
To understand this check the definition of statement:
Expression statements cause expressions to be evaluated. No transfer
of control or iteration takes place as a result of an expression
statement.
The syntax for the expression statement is simply Syntax
[expression ] ;
and here is the compound statement block definition
A compound statement consists of zero or more statements enclosed in
curly braces ({ }). A compound statement can be used anywhere a
statement is expected. Compound statements are commonly called
"blocks." Syntax
{ [ statement-list ] }
Verdict: Your assumption was valid, your fear unfounded :)

c++ for loop: 'i' was not declared in this scope

bool linear_search(const string A[], int n, string colour, int &count)
{
for (int i = 0; i < n; i++);
{
if (colour == A[i])
{
return true;
}
}
return false;
}
Compiling the above code results in the error 'i' was not declared in this scope for the if statement if (colour == A[i]).
This is really similar to many other for loops I have written, and I don't understand why it is not declared in the scope. Wasn't it declared in the previous line? How do I fix this?
You have a semi colon after your for loop declaration, remove it and you will be fine.
As others have pointed out, the problem is an extra semicolon that prevents your intended loop body from actually being part of the loop. But I want to provide more information on how to catch and avoid this kind of error.
First of all, when I compile the code with the formatting you show, my compiler produces a warning:
main.cpp:130:32: warning: for loop has empty body [-Wempty-body]
for (int i = 0; i < n; i++);
^
You should check to see if you're already getting this or some similar warning, and if so you should make sure to pay attention to warnings in the future. If you're not getting this warning, see if you can increase your compiler's warning level in some way to cause it to produce a warning like this. Enabling and paying attention to compiler warnings can save you a lot of trouble.
Next, I notice that your code is poorly formatted. Poor formatting can hide this sort of error. When I auto-format the code it becomes:
bool linear_search(const string A[], int n, string colour, int &count) {
for (int i = 0; i < n; i++)
;
{
if (colour == A[i]) {
return true;
}
}
return false;
}
This formatting makes the extraneous semicolon much more obvious. (It also suppresses my compiler's warning about the empty body, since the compiler assumes that if you put the empty body on a separate line then you really mean for it to be empty.) Using automatic formatting avoids the problems of inconsistent formatting and ensures that the formatting is consistent with the actual meaning of the code. See if your editor provides formatting support or see if you can integrate an external formatter like clang-format.
Are you sure you need ; in this line? for (int i = 0; i < n; i++);
you ended for loops block by adding a ; after for loop
for (int i = 0; i < n; i++);
remove this semicolon.
I had a similar problem but there was an "if" statement before my variable declaration in front of a "for" loop, the error was the same. Just in case that somebody googled it and didn't mention something like that:
if (someVar!=1) // an "if" statement that reduces the scope of "var"
//some comment line
//some other comment line
double var = 0.0;
for (size_t i = 0; i < length; i++) {
var *= 0.5; // Error appeared here
}

Unreachable code in for loop increment?

I'm getting a C4702: unreachable code warning in a for loop; the strange thing is that - by breaking apart the components inside the parens - the warning points to the increment part. Here's a sample program that demonstrates this error:
int main()
{
int foo = 3;
for (int i = 0;
i < 999;
i++) // warning on this line
{
if (foo == 4);
{
break;
}
}
return 0;
}
I can't figure out what's wrong with this line, because the for loop looks very straight-forward.
You have a stray semicolon in your if-statement:
if (foo == 4);
Recall that for loops have the following structure:
for (initialisation; condition; increment/decrement)
statement
Execution will proceed in the following order:
initialisation
condition; if false then end
statement
increment/decrement
Go to step 2
If the compiler is warning about the increment/decrement being unreachable, it means that something before it is causing execution to always skip it - in this case, the stray semicolon causes the break to always execute, jumping out of the loop prematurely.
for (int i = 0;
i < 999;
i++) // warning on this line
{
if (foo == 4);
{
break;
}
}
This is same as
for (int i = 0;
i < 999;
)
{
if (foo == 4);
{
break;
}
i++; /* Note the increment here */
}
So anyways you are going to break because of the if(foo == 4); so i++ is not reachable
The problem (i.e. the unintended ;) is already described in two answers.
I just like to add that you should take a look at your compiler options setting. Many compilers can detect such "strange looking" code and give you a warning. For instance:
Warning: "empty body in an 'if' statement"
Further the compiler can be configured to treat all warnings as errors.
In other words - the compiler options can often help you finding "unintended code" so that you avoid wasting time.
BTW - the eclipse editor can even give a "suspicious semicolon" warning as soon as you type such an if-statement.

Invalid use of auto

In this code:
for ( ;(auto i = std::find(some_string.begin(),some_string.end(),'%')) != some_string.end();)
{
}
I'm getting error from gcc 4.7.1:
error: invalid use of 'auto'|
any ideas why? shouldn't that be correctly compiled?
I think it has nothing to do with auto. You just cannot declare variables in random places, for example this will not compile either - an equivalent of what you were trying to do, but without auto:
int main() {
for ( ; (int i = 0) != 1; ++i)
;
return 0;
}
If this is in a loop, you'll only ever find the first '%'. You need to resume searching from i, not some_string.begin() to find subsequent '%'.
auto i = std::find(some_string.begin(), some_string.end(), '%'));
while (i != some_string.end()) {
// Your code here.
i = std::find(i, some_string.end(), '%')); // Find next '%'.
}

Why are empty expressions legal in C/C++?

int main()
{
int var = 0;; // Typo which compiles just fine
}
How else could assert(foo == bar); compile down to nothing when NDEBUG is defined?
This is the way C and C++ express NOP.
You want to be able to do things like
while (fnorble(the_smurf) == FAILED)
;
and not
while (fnorble(the_smurf) == FAILED)
do_nothing_just_because_you_have_to_write_something_here();
But! Please do not write the empty statement on the same line, like this:
while (fnorble(the_smurf) == FAILED);
That’s a very good way to confuse the reader, since it is easy to miss the semicolon, and therefore think that the next row is the body of the loop. Remember: Programming is really about communication — not with the compiler, but with other people, who will read your code. (Or with yourself, three years later!)
I'm no language designer, but the answer I'd give is "why not?" From the language design perspective, one wants the rules (i.e. the grammar) to be as simple as possible.
Not to mention that "empty expressions" have uses, i.e.
for (i = 0; i < INSANE_NUMBER; i++);
Will dead-wait (not a good use, but a use nonetheless).
EDIT: As pointed out in a comment to this answer, any compiler worth its salt would probably not busy wait at this loop, and optimize it away. However, if there were something more useful in the for head itself (other than i++), which I've seen done (strangely) with data structure traversal, then I imagine you could still construct a loop with an empty body (by using/abusing the "for" construct).
OK, I’ll add this to the worst case scenario that you may actually use:
for (int yy = 0; yy < nHeight; ++yy) {
for (int xx = 0; xx < nWidth; ++xx) {
for (int vv = yy - 3; vv <= yy + 3; ++vv) {
for (int uu = xx - 3; uu <= xx + 3; ++uu) {
if (test(uu, vv)) {
goto Next;
}
}
}
Next:;
}
}
I honestly don't know if this is the real reason, but I think something that makes more sense is to think about it from the standpoint of a compiler implementer.
Large portions of compilers are built by automated tools that analyze special classes of grammars. It seems very natural that useful grammars would allow for empty statements. It seems like unnecessary work to detect such an "error" when it doesn't change the semantics of your code. The empty statement won't do anything, as the compiler won't generate code for those statements.
It seems to me that this is just a result of "Don't fix something that isn't broken"...
Obviously, it is so that we can say things like
for (;;) {
// stuff
}
Who could live without that?
When using ;, please also be aware about one thing. This is ok:
a ? b() : c();
However this won't compile:
a ? b() : ; ;
There are already many good answers but have not seen the productive-environment sample.
Here is FreeBSD's implementation of strlen:
size_t
strlen(const char *str)
{
const char *s;
for (s = str; *s; ++s)
;
return (s - str);
}
The most common case is probably
int i = 0;
for (/* empty */; i != 10; ++i) {
if (x[i].bad) break;
}
if (i != 10) {
/* panic */
}
while (1) {
; /* do nothing */
}
There are times when you want to sit and do nothing. An event/interrupt driven embedded application or when you don't want a function to exit such as when setting up threads and waiting for the first context switch.
example:
http://lxr.linux.no/linux+v2.6.29/arch/m68k/mac/misc.c#L523