2

I'm reading a book in C and have seen these two strcmp algorithm.

I have learned my self how the usel for loop works.

But these two for loop are new for me. I don't understand these parts

  1. for (i = 0; s[i] == t[i]; i++) It have no length instead have this s[i] == t[i].

  2. for ( ; *s == *t; s++, t++) what means this guy ;.

The other parts i understand and I'm also aware what these function returns.

   /* strcmp: return <0 if s<t, 0 if s==t, >0 if s>t */
int strcmp(char *s, char *t)
{
   int i;
   for (i = 0; s[i] == t[i]; i++)
       if (s[i] == '\0')
     return 0;
   return s[i] - t[i];
}

int strcmp(char *s, char *t)
{
 for ( ; *s == *t; s++, t++)
  if (*s == '\0')
  return 0;
 return *s - *t;
}
S landy
  • 33
  • 3
  • The `;` divides the `for` into three parts, all of which are optional. The first part is executed before the first loop test. The second part is the loop test before each iteration, defaulting to true if empty. The third part is executed at the end of a loop iteration before the next loop test. – Ian Abbott Apr 25 '17 at 17:21
  • The structure of the `for` loop is as follows: `for ( ; ; )`. And `for ( ; ; )` is an infinite loop. – ForceBru Apr 25 '17 at 17:22

5 Answers5

2

First, some basics.

The syntax of a for loop is

for ( expr1opt ; expr2opt ; expr3opt ) statement

Each of expr1, expr2, and expr3 are optional. The statement

for ( ; ; ) { // do something }

will loop "forever", unless there's a break or return statement somewhere in the body of the loop.

expr1, if present, is evaluated exactly once before loop execution - it's used to establish some initial state (such as setting an index to 0, or assigning a pointer value, or something like that).

expr2, if present, is evaluated before each iteration of the loop body. It's the test condition for continuing loop execution. If the expression evaluates to a non-zero value, the loop body is executed; otherwise, the loop exits. If expr2 is missing, it is assumed to evaluate to 1 (true).

expr3, if present, is evaluated after each iteration of the loop body. It usually updates whatever is being tested in expr2.

for (i = 0; s[i] == t[i]; i++) It have no length instead have this s[i] == t[i]

This loop will execute as long as s[i] == t[i]; as soon as t[i] is not equal to s[i], the loop will exit. By itself, this means the loop will run past the end of the string in case you have identical strings - if both s and t contain "foo", then the loop will run as

s[0] == t[0] == 'f'
s[1] == t[1] == 'o'
s[2] == t[2] == 'o'
s[3] == t[3] == 0
s[4] == t[4] // danger, past the end of the string

So, within the body of the loop, the code also checks to see if a[i] is 0 - if so, that means we've matched everything up to the 0 terminator, and the strings are identical.

So, basically, it goes...

s[0] == t[0] == 'f', s[0] != 0, keep going
s[1] == t[1] == 'o', s[1] != 0, keep going
s[2] == t[2] == 'o', s[2] != 0, keep going
s[3] == t[3] == 0, s[3] == 0, at end of s, strings match

for ( ; *s == *t; s++, t++)

does exactly the same thing as the first loop, but instead of using the [] operator to index into s and t, it just uses the pointers. Since there's nothing to initialize, the first expression is just left empty.

John Bode
  • 119,563
  • 19
  • 122
  • 198
1

In the first case, the code after the for statement is checking to see if the end-of-string marker has been found, and if so the function returns 0.

In the case of the second for statement, the initialization part of the for statement is not filled in, so the statement starts with for( ;. This is perfectly legitimate.

Best of luck.

1

For loop has 3 parts - initialization , condition and loop expresion. All these are optional.
So this loop-

for (i = 0; s[i] == t[i]; i++)

It runs till character s[i] is equal to t[i]. So this is condition. If it is false loop breaks.

It is not necessary that condition is always based on length.

And this one -

for ( ; *s == *t; s++, t++)  

As we see above intialization is optional and is not present here which is perfectly fine. Condition in this loop is also same i.e loop till characters are equal.

ameyCU
  • 16,489
  • 2
  • 26
  • 41
1

for (i = 0; s[i] == t[i]; i++) // It has no length

Actually this code is slightly dangerous, as it assumes that the passed strings are NULL-terminated (but read later). The cycle goes on only while the left-part of the strings are equal so, inside the loop, the only possible result to be returned is 0 (equal), when a NULL is encountered (the for(;;) condition ensures that the two strings both have the NULL in the same position).

About the length, to calculate it you should scan the whole string anyway... and two times (because there are two strings). This cycle instead combines all in one. Moreover, strings in C must be NULL terminated. Definitely, there is no other way to do this comparison!

for ( ; *s == *t; s++, t++) // what means this guys

This is about the same as the previous, but instead of dereferencing s and t using an index (and without touching them), they are modified to point to the characters, one after another. I believe this is faster, but depends on the compiler. Moreover, incrementing s and t makes you lose the start of the strings; but in this function it is not a problem.

About the syntax of for(;;), a comment already explained why it is written like this. The last part of the for(), between the semicolon and the closing bracket, is executed after every iteration. In this case we need to increment two variables, so there are two statements separated by a comma.

1
  1. It doesn't have be a length. The for loop is run until the condition is true, so in this case it means it will be running until s[i] is not equal to t[i].

  2. for ( ; *s == *t; s++, t++)

; here means that the first clause of the for loop is omitted. As bot s and t are defined outside of for loop there is no need to define them here.

It's allowed by the C standard:

for ( clause-1 ; expression-2 ; expression-3 ) statement

(...)

Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a nonzero constant.

Some compilers such as clang produce a warning when an already defined variable is put in the first clause. For example this code:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  int i = 0;
  for (i; i < 10; i++)
    puts("Hi");

  return EXIT_SUCCESS;
}

compiled with clang produces a warning:

main.c:7:8: warning: expression result unused [-Wunused-value]
  for (i; i < 10; i++)
       ^
Arkadiusz Drabczyk
  • 11,227
  • 2
  • 25
  • 38