0

From this answer, I saw this:

unsigned long
hash(unsigned char *str)
{
    unsigned long hash = 5381;
    int c;

    while (c = *str++)
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */

    return hash;
}

The problem is that I don't see how the while stops from executing. Generally an assignment isn't resulted in true? I mean if(a = 5) will be true.

Also the compiler gave me this warning:

warning: suggest parentheses around assignment used as truth value [-Wparentheses]

Can anyone step me trough on what exactly goes on with the loop? I would strongly suggests that an example would be the best approach here.

Also where should the parentheses go to make this more clear?

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • 2
    _"Generally an assignment isn't resulted in true? I mean if(a = 5) will be true."_ This seems to be a contradiction. – Lightness Races in Orbit Nov 12 '14 at 23:48
  • 2
    _"Also where should the parentheses go to make this more clear?"_ Nowhere, really; the warning is a red herring, designed for other cases. – Lightness Races in Orbit Nov 12 '14 at 23:48
  • The reason for warning is common mistake made by novice programmers, namely using `=` operator instead of `==`. To supress it is to wrap condition with second pair of parantheses e.g. `while ((c = *str++))` – Grzegorz Szpetkowski Nov 12 '14 at 23:53
  • Yeah that's what I did after the answer I received @GrzegorzSzpetkowski and it worked, I just thought that the`++` could be confusing the compiler but that wasn't the case. Thanks! – gsamaras Nov 12 '14 at 23:56
  • 1
    It's not just a common mistake by novice programmers, it's also a common typo by experienced programmers. (It's why a lot of old people write `if (5 == a)`, because if they accidentally typo it as `if (5 = a)` that's an error. But younger programmers don't need to learn that, because modern compilers have warnings like this one.) – abarnert Nov 12 '14 at 23:57
  • the loop stops when the '\0' termination char is encountered at the end of the string. The true/false ness of a expression (as in c = *str++) is determined on the result value. I.E. the value in the 'c' variable. And as we all know, 0 is false and all other values are true. – user3629249 Nov 13 '14 at 04:08
  • 1
    @abarnert: _"it's also a common typo by experienced programmers"_ Speak for yourself but as an experienced programmer I've never made that mistake and neither has anyone around me. It's pretty easy to avoid. _That's_ why we don't switch into horrible Yoda conditions, not because some compiler has a warning diagnostic for it. – Lightness Races in Orbit Nov 13 '14 at 10:16
  • @LightnessRacesinOrbit: Well, it's good to know that you've never made a typo like that, unlike inexperienced novices like, say, the developers of BSD4.4, or gcc's PowerPC optimizer, or other unimportant projects like that. – abarnert Nov 13 '14 at 19:48

1 Answers1

5

The value of an assignment is the value that gets assigned. For example, this code:

int a;
printf("%d\n", a=5);

… will print out 5.

So, this loop runs until c is assigned something false.

And in C, 0 is false, and strings are null-terminated, so at the end of the string, the NUL character, 0, will end the loop.


The warning is because if (a = 5) is a typo for if (a == 5) more often than it's intentional code. Putting extra parentheses around an assignment, like if ((a == 5)), is an idiomatic way to say "I meant to use the value of this assignment". With some compilers, you may get a different, stronger warning in the case where the value is constant, as in my example, than in examples like yours, but the issue is the same: if you meant to test the value of an assignment, and you don't want to disable the warning globally, the way to convince GCC to leave you along is with extra parentheses: while ((c = *str++)).

See this question for more details. You may also want to search the GCC mailing lists for threads like this one discussing the warning.

Community
  • 1
  • 1
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • Correct, I just checked `if(a=0)`. Are you going to mention something for the parentheses there? – gsamaras Nov 12 '14 at 23:51
  • The warning I was talking about is here `while (c = *str++)`. – gsamaras Nov 12 '14 at 23:52
  • @G.Samaras: Yes, that's still an assignment. That doesn't meet the stronger warning about testing assignment to a constant, but it does meet the weaker warning about testing any assignment. – abarnert Nov 12 '14 at 23:52
  • @G.Samaras: OK, I wasn't sure from the last comment, and I figured better to make it absolutely clear than to leave it possibly unclear. – abarnert Nov 12 '14 at 23:58
  • 1
    @G. Samaras, about the parentheses warning. In a statement such as `while ((c = *str++) != 0)` the parentheses are needed do over-ride the precedence of `!=` over `=` but in this case the truth is implied from any non-0 value. – Weather Vane Nov 13 '14 at 00:03