简体   繁体   中英

Pointers with increment and decrement operators

In general, when the assignment operator is there left operand should be a variable and not an expression but when I am making left side an expression using pointers, the code is not producing any error.

Jdoodle online compiler/C

It should throw an error however successful compilation is there.

https://www.jdoodle.com/c-online-compiler

#include <stdio.h>

int main()
{
    int x = 30, *y, *z;

    y = &x; // Assume address of x is 1000 and integer is 4 byte size */
    z = y;
    *y++ = *z++;
    x++;
    return 0;
}

The left operand of an assignment does not have to be a variable. For example, the following assignments should and do work perfectly fine (and I assume you know that and just misspoke):

array[index] = value;
*ptr = value;

I think what's confusing you about *y++ = *z++; is that you think that it's assigning to the result of an increment operation, which would indeed make no sense. But that's not the precedence of that expression: *y++ is equivalent to *(y++) , not (*y)++ . So you're dereferencing the result of y++ and then assign a value to that dereferenced memory location, just as if you had written:

int *ptr = y++;
*ptr = *z++;

In general, when the assignment operator is there left operand should be a variable and not an expression ...

The left operand of an assignment operator is always an expression. The restriction is that it has to be an lvalue , which is (simplifying a bit) an expression that designates an object.

The simplest case of an lvalue is the name of a declared object/variable, so for example:

int n;
n = 42;

n is an expression, specifically an lvalue, that designates the object named n .

In your example, you have:

*y++ = *z++;

Operator precedence says that the ++ operator binds more tightly than the * operator, so this is equivalent to:

*(y++) = *(z++);

y++ and z++ are not values -- they're expressions that yield pointer values, but they don't designate any objects. But the unary * operator gives you an lvalue even when its operand is not an lvalue. y++ yields a pointer value, and *(y++) gives you the object that that pointer points to.

The C standard doesn't use the term "variable" in this sense. It talks about objects , which may or may not be declared objects with simple names. an_object , *pointer_value , array[index] , and structure_object.member all refer to objects and can appear on the left side of an assignment.

left operand should be a variable and not an expression

This is a misunderstanding. The term you are looking for is lvalue . This a C standard gibberish term originating from the term "left value". The definition of the term lvalue is roughly: an expression that designates an object.

The rules for the various operators discussed here are:

  • The left operand of the assignment operators must always be a lvalue.
  • The result of the unary * operator is defined to always be a lvalue, so you can use it as if it was an object, and we can assign to it.
  • The result of the ++ operators however, is not an lvalue, so it cannot be used as the left operand of assignment.

Examples:

int x; int* y;

x = 5;   // Here x is both an object and an lvalue, so the code is valid
y = &x;  // y is both a (pointer) object and an lvalue, code is valid.
*y = 0;  // *y is an lvalue designating the object y, code is valid
y++ = 1; // y++ is not an lvalue, the code is invalid

As for why *y++ works, it is just a matter of operator precedence. The ++ is applied first, but since it is postfix, the change doesn't take place until the end of the expression. So * is applied to y and the result is a lvalue.

Had you written ++*y = 0; then operator associativity had caused the * to execute first, the result *y being an lvalue. And then when you use ++ on that lvalue, the result of ++ is not an lvalue so the code is invalid. ++*y in itself is valid code, but it can't be the left operand of assignment.

Suppose, address of x is 1000 and sizeof(int) = 4 (for a 32-bit compiler), then when you evaluate the expression:

 *y++=*z++;

Address of z is incremented

(Since, post-increment(x++) has higher precedence than ( *x ) )

but before that ie address stored by z is assigned to pointer y . 之前,即由z存储的地址分配给指针yAfter that only increment of address and dereferencing is taking place.

Similar is the case for *y++ , first address is assigned, post-increment occurs and is then dereferenced. If you are confused about lvalue to be a variable, it is not necessary Eg : adding a statement like in your code after initializing the pointer with a valid address



is also correct and will not flag any error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM