eternalmatt
eternalmatt

Reputation: 3564

Why does this C not allow combining -- operator and & operator in this syntax

I'm trying to do something fairly simple. Of course it could be done with an extra line of code, but technically speaking, why does this not work?

int foo = 5;
int *bar = &(--foo);

GCC compiler tells me "invalid lvalue in unary &"

Upvotes: 1

Views: 113

Answers (5)

Suroot
Suroot

Reputation: 4423

I have no clue why you might need to do this; but if the pointers should be equal. If you do it in a statement ( comma delimited) then the last element in the statement is what is returned. The following compiles and both variables are equal according to GCC.

int main(int argc, char *argv[]) {
        int foo = 5;
        int *bar;
        printf("%p\n", &foo);
        bar = (int *)(--foo, &foo);
        printf("%p\n", bar);
        return -1;
}

Upvotes: 0

Yuriy Vikulov
Yuriy Vikulov

Reputation: 2499

because (--foo) is rvalue. like a number constant

Upvotes: 0

Anomie
Anomie

Reputation: 94834

Technically speaking, it doesn't work because --foo is not an lvalue, but the unary & operator requires one.

From the C draft standard, section 6.5.16:

An assignment expression has the value of the left operand after the assignment, but is not an lvalue.

While that doesn't directly cover the prefix decrement operator, section 6.5.3.1 makes it apply:

The expression ++E is equivalent to (E+=1).

and

The prefix -- operator is analogous to the prefix ++ operator, except that the value of the operand is decremented.

And, of course, section 6.5.3.2:

The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.

Upvotes: 2

paxdiablo
paxdiablo

Reputation: 882226

Because --foo is not an lvalue (so named since they typicaly appeared on the left of an asignment).

It's the same problem with:

--foo = 7;

If, for some bizarre reason, you need it on one line, just use:

--foo; int *bar = &foo;

If you think you need it in one instruction, think again. Even if you make such a horrible monstrosity (a), it will probably compile down to the same machine language sequence as that code snippet above.


(a) int *bar = (--foo, &(foo));

Upvotes: 5

xappymah
xappymah

Reputation: 1644

Because --foo returns some temporal value, but & needs a variable to create a reference to it. So, you need do it in two steps:

int *bar = &foo;
--foo;

Upvotes: 1

Related Questions