In this C code, how an expression can act like a logical

Basically, I have two questions in the following code:

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 lines to one. But how is this line while (*z++ = *x++); can act like boolean 1/0 , and why do I even set malloc(0); to zero, does it also work well without any problems?

+5
source share
6 answers

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

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

This is a good source of errors due to the nebula:

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

And why I even installed malloc(0); to zero, does it also work well without any problems?

Using the returned malloc(0) value to write values ​​is simply undefined and "works by accident." You request null bytes, so you are never allowed to write this distribution, and malloc() may even return you a null pointer.

Quoting yourself here about undefined behavior:

Undefined behavior in C

C is a very low level language, and one of the consequences of this is the following:

Nothing will ever stop you from committing something completely wrong.

Many languages, especially for some managed environment, such as Java or C# actually stop you when you do something that is not allowed, say, access to an array element that does not exist. C no. As long as the program is syntactically correct, the compiler will not complain. If you do something forbidden in your program, C simply causes the behavior of your program to be undefined . This formally allows something to happen when the program starts. Often the result will be a crash, or simply the output of "garbage", as seen above. But if you are really unlucky, your program will seem to work very well until it receives a slightly different contribution, and thus time, it will be very difficult for you to determine exactly where your program is undefined. Therefore, avoid undefined behavior in every way! .

On the other hand, undefined behavior can also cause security holes. This practice has happened a lot.

+6
source

In C, any expression can be used as a Boolean. 0 (or null for pointers) means false, a nonzero value means true.

It even includes appointments. An expression is assigned, then evaluated. So you can have code like

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

This is what tends to give C a bad name, but it is allowed.

+3
source

To reply:

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

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

Big big disclaimer: This code dereferences the pointer obtained using malloc(0) , which is already very similar to undefined behavior, and therefore it makes no sense to speculate on why this code works or does not work.

+2
source

An assignment has a value that is its left side like this:

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

So, if(a = b){} - this is how to say a = b; if(a){} a = b; if(a){} .

In C any non-zero numeric value or pointer is true, and only zero 0 or zero pointer false.

So, the expression if(*x){} true if the char pointed to by x is any character other than the null delimiter character '\0' .

Putting it all together:

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

Take the char that y points to and copy it to the char that x points to. Then increase both x and y . Execute the while body if char not a null terminator of '\0' .

Equivalent Type:

 *x = *y exp = *x; x++; y++; if(exp){} 
+1
source

Condition

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

may be cryptic due to the concept of C expression, which is different from some other languages. Note that, strictly speaking, C has no Boolean type. In addition, the assignment expression itself has a meaning, namely the assigned value.

0
source

There are some problems with your code.

First, const char *x = "abc" initializes x a pointer value, sometimes indicating read-only in the executable file zone, and tries to initialize by indirectness, therefore *x = something will be segfault due to the lack of write permission in this segment .

Next, x = malloc(0) is the correct call and the only valid operation you can do with the returned x pointer is free(x) - read the malloc man page.

If the size is 0, malloc () returns either NULL or a unique pointer to a value that can subsequently be successfully passed to free ()

Finally, your code is rewritten like this: suppose you do x in the write zone.

 void foo() { char*a,*b; a=calloc(100,1); b=calloc(100,1); memcpy(b,"",4); printf("%p %p `%s `%s\n",a,b,a,b); loop: *a=*b; if (!*b) goto end; /* sequence point after controlling expression of `while`*/ a=a+1; b=b+1; goto loop; end: a=a+1; b=b+1; printf("%p %p `%s `%s\n",a,b,a,b); } int main() { char*a,*b; a=calloc(100,1); b=calloc(100,1); memcpy(b,"",4); printf("%p %p `%s `%s\n",a,b,a,b); while(*a++=*b++); printf("%p %p `%s `%s\n",a,b,a,b); foo(); return 0; } 

The only problem here is evaluating the state of the while statement.

6.8.5.1 while statement

1 Evaluation of the control expression takes place before each execution of the body of the cycle.

0
source

Source: https://habr.com/ru/post/1269020/


All Articles