2

Possible Duplicate:
How does “while(*s++ = *t++)” work?

I had the following question during an interview. Can someone please explain it to me?

void question( char *s, char *t)
{
  while (*s++ = *t++);
}
Community
  • 1
  • 1
Simon
  • 4,999
  • 21
  • 69
  • 97
  • 8
    They tricked you by asking a C question in a C++ interview :) . C++ uses `std::string` and rarely `char *` – Alok Save Aug 30 '12 at 07:01
  • 2
    http://stackoverflow.com/questions/810129/how-does-whiles-t-work see this – Arpit Srivastava Aug 30 '12 at 07:02
  • 2
    What is the question you would like explained? – jalf Aug 30 '12 at 07:11
  • 1
    They probably wanted to see if you have read K&R. – fredoverflow Aug 30 '12 at 07:16
  • 2
    @FredOverflow: Or perhaps they wanted to start a discussion of buffer overflows, security vulnerabilities, and the importance of checking input. We'll never know. – Mike Seymour Aug 30 '12 at 07:20
  • @Fred: I've read K&R, over 10 years ago. I'd *hope* that a qualified C or C++ programmer can work out what this does for themselves, though, rather than by remembering something they read 10 years ago! I expect this probably works as an entry-level, "can you actually read C, or did you just do a course on it?" question. Remarks like "it does the same as `strcpy`", "this is C++, I'd use `string`" or "I'd like to discuss buffer overflows" are probably pure bonus from the POV of the interviewer, because even the best C++ programmer might pick a different remark according to mood ;-) – Steve Jessop Aug 30 '12 at 10:35

3 Answers3

4

It introduces a massive security vulnerability into your program. Do not write, or use, code like this under any circumstances.

If we break the code down, we get:

  • *t++ reads the character pointed to by t, and increments t; the expression's value is the character that was read.
  • *s++ = expression writes that character to where s points, and increments s; the expression's value is the character that was written.
  • while (expression); keeps looping as long as the expression's value is non-zero; in this case, until we wrote a character with the value zero.

So the function keeps copying characters from t to s until it reaches a zero-valued character. There is no way to tell whether s points to a large enough array to hold these, so in general it will write beyond the end of the array and cause undefined behaviour; anything from subtle behaviour with no unwanted effects, to a crash, to the execution of malicious code.

You can only call this function if you know in advance (an upper bound for) how many characters will be copied; if you know that, then there are (usually) more efficient ways to copy the data than to check the value of each. Therefore, you should (almost) never use this function, or the C library function (strcpy) that it approximates.

This use of a zero-valued character to terminate a string is a common idiom in C; in C++ it is usually more convenient to use the std::string class to represent strings instead. In that case, the equivalent code would be simply s = t, which would manage the strings' memory safely.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • "You can only call this function if you know in advance how many characters will be copied" - false. You can use it if you do not know in advance the exact number of characters, but do know an upper limit. – Steve Jessop Aug 30 '12 at 10:49
  • @SteveJessop: Yes, I though about adding that qualification, but didn't bother. I really should know by now that I can't get away with simplifications on this site. – Mike Seymour Aug 30 '12 at 10:50
  • We're always watching, us pedants. I suspect (but can't prove) that in the very rare cases where you'd actually consider using it like that, you are in any case going to want `stpcpy` rather than `strcpy`, because the return value from `strcpy` is next to useless. – Steve Jessop Aug 30 '12 at 10:51
3

Copies the string, pointer by t to the memory, pointed by s.


operator= will return the assigned value. t is supposed to point to a NULL-terminated string and s should point to memory, large enough to store that string.

So, the while loop will stop when \0 is hit, which is the end of the string, pointed by t. During this while loop, all chars (different from \0) in t will be copied into s.


Expanded a little, it's the same as:

while( *t != '\0' ) // while the current char is not NULL
{
    *s = *t; // copy it into s
    ++s; // increment s, to point to the next byte
    ++t; // increment t, to point to the next char, that will be copied
}
*s = *t; // copy the last char of t - the '\0'
Kiril Kirov
  • 37,467
  • 22
  • 115
  • 187
  • 1
    Your loop and the compact one are not the same. Yours does not copy the null character that terminates the string. The compact one does. – David Hammen Aug 30 '12 at 07:31
  • @DavidHammen - thanks, you're absolutely right. – Kiril Kirov Aug 30 '12 at 07:36
  • Also equivalent and easy to read (but probably poor style because we hates `break`, it wants our precioussss): `while(1) { *s = *t; if (*s == 0) break; ++s; ++t}`. There's another slight difference between Kiril's loop and mine on one side, and the loop in the question on the other, which doesn't matter in this case because the function exits immediately: we leave `s` and `t` pointing to the nul terminators, whereas the loop in the question advances them past it. – Steve Jessop Aug 30 '12 at 10:43
2

It copies null-terminated string t into s. Semantics as strcpy.

demi
  • 5,384
  • 6
  • 37
  • 57
  • 1
    Except that strcpy is declared as `char* strcpy(char*, const char *);`. – john Aug 30 '12 at 07:02
  • 4
    Thank you John, but semantics - what function does - still the same - it copies null-terminated string pointed by second argument into first, large enough. – demi Aug 30 '12 at 07:10