5

Basically I have two questions in the code bellow:

const char *x = "abc";
const char *y = "def";

char *res = (char*)malloc(0);
char *z = res;
while (*z++ = *x++);
z--; // remove \0
while (*z++ = *y++);

printf("%s\n", res); // output: abcdef
free(res);

The purpose of this code is to add two strings in one. But how this line while (*z++ = *x++); can act as boolean 1/0, And why I even set the malloc(0); to zero it also works well without any problem??

alinsoar
  • 15,386
  • 4
  • 57
  • 74
Bahramdun Adil
  • 5,907
  • 7
  • 35
  • 68

5 Answers5

6

But how this line while (*z++ = *x++); can act as boolean 1/0

This is because in C, an assignment is an expression and it evaluates to the value that is assigned. When *x reaches the final '\0' terminator, it evaluates to 0, therefore false in a boolean context.

This is btw a nice source of bugs due to mistyping:

if (x = 1) // always true, as a side effect assigns 1 to x

And why I even set the malloc(0); to zero it also works well without any problem??

Using the return value of malloc(0) to write values is just undefined and "works by accident". You request zero bytes, so you are never allowed to write to this allocation and malloc() could even return you a null pointer.

Citing myself here about undefined behavior:

Undefined behavior in C

C is a very low-level language and one consequence of that is the following:

Nothing will ever stop you from doing something completely wrong.

Many languages, especially those for some managed environment like Java or C# actually stop you when you do things that are not allowed, say, access an array element that does not exist. C doesn't. As long as your program is syntactically correct, the compiler won't complain. If you do something forbidden in your program, C just calls the behavior of your program undefined. This formally allows anything to happen when running the program. Often, the result will be a crash or just output of "garbage" values, as seen above. But if you're really unlucky, your program will seem to work just fine until it gets some slightly different input, and by that time, you will have a really hard time to spot where exactly your program is undefined. Therefore avoid undefined behavior by all means!.

On a side note, undefined behavior can also cause security holes. This has happened a lot in practice.

  • Thanks for your reply, it was really very confusing to me. So it means that the expression also has a return value in C? which while loop can be stopped or run? – Bahramdun Adil Jun 20 '17 at 09:44
  • @BahramdunAdil Don't confuse the terms: An *expression* always has a *value*, this value is what the expression *evaluates* to. You might think that assignment is only a *statement* (something that's executed), but in C, it is *also* an expression, evaluating to the value that is assigned. –  Jun 20 '17 at 09:46
3

In C, any expression can be used as a boolean. 0 (or null for pointers) means "false", non-zero means "true".

This even includes assignments. The expression is assigned, then evaluated. So you can have code like

while(*dest++ = *src++);

This is the sort of thing that tends to give C a bad name, but it is allowed.

Malcolm McLean
  • 6,258
  • 1
  • 17
  • 18
2

To answer :

But how this line while (*z++ = *x++); can act as boolean 1/0

This while loop will run until *z points to NUL, since the string literal contains "abc\0" this will loop over a, b, c then it will encounter \0 which converts to 0 which will not satisfy the while and thus it terminates.

Big big disclaimer though: This code is dereferencing a pointer that was obtained by malloc(0), that is already very much undefined behaviour and thus there's no point in reasoning why this code works or doesn't work.

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122
1

An assignment has a value, which is its left-hand side so:

a = b; // value of the expression is a, after the assignment

So if(a = b){} is like saying a = b; if(a){}.

In C any non zero numeric value or pointer equals true and only zero 0 or a null pointer is false.

So the expression if(*x){} is true if the char pointed to by x is any character except the null terminator character '\0'.

Putting it all together:

if(*x++ = *y++){}

Take the char pointed to by y and copy it to the char pointed to by x. Then increment both x and y. Execute the while body if that char was not the null terminator '\0'.

Sort of equivalent to:

*x = *y
exp = *x;
x++;
y++;
if(exp){}
Galik
  • 47,303
  • 4
  • 80
  • 117
0

The condition

while (*z++ = *x++)

might be puzzling because of the expression concept of C which differs from some other languages. Note that strictly speaking, C does not have a boolean type. Furthermore, an assignment expression itself has a value, namely the assigned value.

Codor
  • 17,447
  • 9
  • 29
  • 56