Reputation: 47
i just saw this "while(something);" syntax. i googled this but did not found anything. how does this work? especially second while in the example code confuses me.
this code is a program to concatenate two strings using pointer.
#include <stdio.h>
#define MAX_SIZE 100 // Maximum string size
int main()
{
char str1[MAX_SIZE], str2[MAX_SIZE];
char * s1 = str1;
char * s2 = str2;
/* Input two strings from user */
printf("Enter first string: ");
gets(str1);
printf("Enter second string: ");
gets(str2);
/* !!!!!!!!!!!!!!!!! this is it!!!!!!!!!!!!!!!!!!!! Move till the end of str1 */
while(*(++s1));
/* !!!!!!!!!!!!!!!!! this is it!!!!!!!!!!!!!!!!!!!! Copy str2 to str1 */
while(*(s1++) = *(s2++));
printf("Concatenated string = %s", str1);
return 0;
}
Upvotes: 1
Views: 535
Reputation: 310950
The while loop is defined in C the following way
while ( expression ) statement
In this while loop
while(*(++s1));
the statement is a null statement. (The C Standard, 6.8.3 Expression and null statements)
3 A null statement (consisting of just a semicolon) performs no operations.
So in the above while loop the expression is evaluated cyclically until it logically becomes false.
Pay attention to that this while loop has a bug.;)
Let's assume that the pointed string is empty ""
. In memory it is represented the following way
{ '\0' }
So initially s1
points to the terminating zero.
But before dereferencing it is incremented in the expression of the while loop
while(*(++s1));
^^^^
and after that points in the uninitialized part of the character array after the terminating zero '\0'
. So the loop can invoke undefined behavior.
It would be more correctly to rewrite it like
while( *s1 != '\0' ) ++s1;
In this case after the loop the pointer s1
will point to the terminating zero '\0'
of the source string.
This while loop where the statement is again a null statement
while(*(s1++) = *(s2++));
can be rewritten the following way
while( ( *s1++ = *s2++ ) != '\0' );
that is in essence the same as
while( ( *s1 = *s2 ) != '\0' )
{
++s1;
++s2;
}
(except that if the terminating zero was encountered and copied the pointers are not incremented)
That is the result of the assignment ( *s1 = *s2 ) is the assigned character that is checked whether it is equal already to the terminating zero character '\0'. And if so the loop stops and it means that the string pointed to by the pointer s2 is appended to the string pointed to by the pointer s1.
Pay attention to that the function gets is unsafe and is not supported by the C Standard. Instead you should use the function fgets
as for example
#include <string.h>
#include <stdio.h>
//...
printf("Enter first string: ");
fgets(str1, sizeof( str1 ), stdin );
str1[ strcspn( str1, "\n" ) ] = '\0';
The last statement is used to remove the new line character '\n'
that can be appended to the entered string by the function call.
Also you need to check in the program whether there is enough space in the array str1
and the string stored in the array str2
can be indeed appended to the string stored in the array str1
.
Upvotes: 2
Reputation: 213690
while(*(++s1));
is an obfuscated and bugged way of writing while(*s1 != '\0') { s1++; }
.
(It should have been while(*(s1++));
to behave as expected, but that too is wrong since it increments the pointer upon failure and won't work with an empty string.)
while(*(s1++) = *(s2++));
is an obfuscated (and likely inefficient) way of writing strcpy(s1,s2);
.
The whole program is an obfuscated way of writing strcat(s1, s2);
. You can replace both of these buggy while
loops with that single function call.
Generally while(something);
is bad practice, to the point where compilers might even warn for it, since it isn't clear if the semicolon ended up there on purpose or by a slip of the finger. Preferred style is either:
while(something)
; // aha this was surely not placed there by accident
or
while(something){}
or
while(something)
{}
Upvotes: 1
Reputation: 9855
The loop
while(*(++s1));
doesn't need a body because everything is done inside the loop condition.
Therefore the loop body is an empty statement ;
.
The loop consists the following steps:
++s1
increment pointer*(...)
dereference pointer, i.e. get the data where the pointer points to.0
is false
, everything else is true
)The loop can be rewritten as
do
{
++s1;
}
while(*s1); // or while(*s1 != '\0');
Similarly, the other loop
while(*(s1++) = *(s2++));
can be written as
do
{
char c;
*s1 = *s2;
c = *s1;
s1++;
s2++;
}
while(c != '\0')
Note that the original loop condition contains an assignment (=
), not a comparison (==
). The assigned value is used as the loop condition.
Upvotes: 0
Reputation: 313
++s1
advances (or increments) the pointer, before the while checks it valuewhile
loop will iterate through the string until it will reach the null terminator, since while(NULL)
is equal to while(false)
or while(0)
Upvotes: 0