sony
sony

Reputation: 395

Is this condition checking statement legal in a for loop?

for (i = 0; *(str+i); i++)
{
    //some code;
}

What is meant by the second condition in this syntax? Can we write it like this?

Upvotes: 3

Views: 191

Answers (7)

Vlad from Moscow
Vlad from Moscow

Reputation: 311068

Such loops usually used for arrays that have a sentinel value that can be converted to a bool value. For example for strings. (Strings are terminated by zero character)

For example this loop calculates length of string literal "Hello"

const char *str = "Hello";

size_t i = 0;
for ( ; *( str + i );  i++ )
{
    /* empty body of the loop */
}

std::cout << "The length of string literal " << str 
          << " is equal to " << i << std::endl;

Or in C you can use printf

printf( "The length of string literal %s is equal to %zu\n", str, i ); 

Expression *( str + i ) is equivalent to str[i]

In the for loop this expression used like the condition is equivalent to

*( str + i ) != 0

That is it is just converted to type bool

( bool ) *( str + i )

So if the expression is equal to 0 then it yields false otherwise true.

Another example. If you want to output program parameters then you can write the following way

#include <iostream>

int main( int argc, char *argv[] )
{
    while ( *argv ) std::cout << *argv++ << std::endl;
}

Ot in C

while ( *argv ) puts( *argv++ );

Because the last element of the array with program parameters argv[] is always equal to NULL.

The while loop in the program is equivalen to the following for loop

for ( int i = 0; *( argv + i ); i++ )

Or

for ( int i = 0; argv[i]; i++ )

From the C++ Standard (5.2.1 Subscripting)

1 A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type “array of T” or “pointer to T” and the other shall have unscoped enumeration or integral type. The result is of type “T.” The type “T” shall be a completely-defined object type.65 The expression E1[E2] is identical (by definition) to *((E1)+(E2))

The same is valid in C.

Upvotes: 5

Shrinath
Shrinath

Reputation: 362

The statement is correct. Yes, we can use it as *(str+i) it will run until the end of the string. Where as *provide value at particular address.

Example:

char str[5]={"test"};

cout<<*str;     // it will always give default first index value

cout<<*(str+1) // it will display first character of string

So when it gets to the end of the string it will become null. The end of the string is always a null character. So then Loop will terminate.

Upvotes: 2

gsamaras
gsamaras

Reputation: 73394

Yes it is. str is a pointer, thus when the string null terminator ('\0') is reached, the condition will be false, making the loop stop from executing its body.

Imagine that the string will be something like this:

str: 'a'|'b'|'\0'
i:    0 | 1 | 2

So when i gets the value 2, then this *(str+i) will give 0, thus your loop will be like this at that time:

for (i = 0; 0; i++)

since the pointer arithmetic will result in *(str+i) to point to the last entry of the string.

Upvotes: 3

Sourav Ghosh
Sourav Ghosh

Reputation: 134356

Just to add clarity, the for loop construct

for (i = 0; *(str+i); i++)

can be re-written as

 for (i = 0; str[i]; i++)  //pointer arithmetic

which can be re-written as

 for (i = 0; (str[i] != 0); i++)  //condition checking

so, essentially, the *(str+i) is a condition checking statement (similar to the most-widely used condition checking statements involving < / > operators), which is perfectly valid and legal.

The purpose it serves is, looping until the ith element is not null.

A null has a decimal value of 0, FWIW.

Upvotes: 1

R Sahu
R Sahu

Reputation: 206697

In its most generic form, the for loop contains the following elements:

for ( init-statement; condition-statement; iter-statement ) statement 

What goes in each of those elements is very open. In your case, the condition-statement is just *(str+i). If it evaluates to a non-zero value, the statement part of the loop will be exeucted. If it evaluates to a zero value, the loop will be terminated.

When you want to execute statement a given number of times, you can use:

for ( i = 0; i < count; ++i ) { ... }

Assuming str in your code points to null terminated string, you are executing statement for all the characters in str. Your for loop is equivalent to:

for (i = 0; str[i] != '\0';  i++)

Upvotes: 2

unxnut
unxnut

Reputation: 8839

The second statement in the loop checks for a condition to be true. If the condition is true, the loop continues; if it is false, the loop is terminated. Additionally, C considers 0 to be false and anything non-zero to be true. So, *(str+i) evaluates to true if it is non-zero and false if it is zero. Since each string in C is a character array that is terminated by \0 (or zero which evaluates to false), looking at the string terminating character evaluates to false and hence, the statement is legal and valid.

For more on why it happens like this in C, it is a side effect of loading something in the accumulator of the Arithmetic Logic Unit (ALU) which results in setting of some flags (such as whether ACC is zero).

Upvotes: 1

haccks
haccks

Reputation: 106092

*(str+i) is equivalent to str[i] provided that str is a pointer to some data type. This is a valid syntax.
It seems that str is a null terminated string. This condition will false when *(str+i) will be equal to '\0'.

Upvotes: 2

Related Questions