Home > Software engineering >  copying one string to another without using strcpy using while loop
copying one string to another without using strcpy using while loop

Time:04-01

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;
}

CodePudding user response:

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 to

int i = -1;
while(true) {
    i  ;
    arr2[i] = arr1[i];
    if(!arr2[i])
        break;
};

Except that one would normally start at i = 0; and put i ; 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 that arr1 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 indexing arr1[i], but before indexing arr2. As a consequence you are not copying to the beginning of arr2. 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. Prefer std::size_t (which however is unsigned and so the first variant won't work).

CodePudding user response:

Utilities for things like copying strings should be written in functions, not inline every place they're used. That makes it simpler to avoid the complexities of incrementing the same variable twice:

void copy_string(char* dest, const char *src) {
    while (*dest   = *src  )
        ;
}

Yes, I know, some people like to have their compiler ignore the rules and refuse to compile valid, well-defined code like this. If your compiler is set that way, figure out how to rewrite that code to make your compiler happy, and perhaps think about who's the boss: you or your compiler.

  • Related