So i recently stumbled on this code somewhere where it is copying one string to another using just one line of code with the help of a while loop , however , I am not able to understand as to how and why it happens-:
int main()
{
char arr1[100];
cin.getline(arr1 , 100);
char arr2[100];
int i = -1;
while(arr2[i] = arr1[++i]);
cout<<arr1<<endl<<arr2<<endl;
return 0;
}
Can somebody explain me what is happening in the backdrop? and moreover if the above code works fine then why dont the below ones?
int main()
{
char arr1[100];
cin.getline(arr1 , 100);
char arr2[100];
int i = 0;
while(arr2[i++] = arr1[i]);
cout<<arr1<<endl<<arr2<<endl;
return 0;
}
another one-:
int main()
{
char arr1[100];
cin.getline(arr1 , 100);
char arr2[100];
int i = 0;
while(arr2[++i] = arr1[i]);
cout<<arr1<<endl<<arr2<<endl;
return 0;
}
The code snippet is relying on an order-of-evaluation guarantee that was added in C++17.
Since C++17 it is guaranteed that the right-hand side of a
=
operator is evaluated first. As a consequence the loop is equivalent toExcept that one would normally start at
i = 0;
and puti++;
at the end of the loop iteration, I think it should be clearer what is happening now. The loop breaks when a null character is encountered, so it expects thatarr1
is a null-terminated string and won't copy the whole array.Before C++17 the order of evaluation was not specified and the code had undefined behavior as a consequence.
If you change the loop to
int i=0; while(arr2[++i] = arr1[i]);
, then (since C++17) you execute++i
only after indexingarr1[i]
, but before indexingarr2
. As a consequence you are not copying to the beginning ofarr2
. Again, before C++17 this is undefined behavior.int i=0; while(arr2[i++] = arr1[i]);
should work correctly since C++17 as well. It does the increment only after indexing both arrays. Again, before C++17 it has undefined behavior.You shouldn't use either of these, since they are hard to reason about and have undefined behavior if the user happens to set the C++ version switch to something before C++17 or tries to use it in C, where it is undefined behavior in all versions.
Also
int
may be too small to hold all indices of a string. Preferstd::size_t
(which however is unsigned and so the first variant won't work).