Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Associativity of unary C Operators (http://www.velocityreviews.com/forums/t445717-associativity-of-unary-c-operators.html)

dspfun 01-01-2007 10:02 PM

Associativity of unary C Operators
 
I'm trying to get a good understanding of how unary operators work and
have some questions about the following test snippets.

int *p;
~!&*++p--;
It doesn't compile, why? The problem seems to be the ++, the compiler
says: "Error: invalid l-value in increment".

int i = 10;
~!*&i++;
It doesn't compile, why? The problem seems to be the ++, the compiler
says: "Error: invalid l-value in unary "&"".

int *p;
~!-&*p--;
It doesn't compile, why? The problem seems to be the -, the compiler
says: "Error: invalid type of argument to unary minus".
I guess the problem is that you can't do unary minus on pointers, and
it doesn't make sense to do so either.

The following does compile on the other hand:
int *p;
p = (int *) = 0x10101010; /*Just to set it to some value..*/
~!&*p--;
p results in having the value 0x1010100c which I understand why.

Is it possible to make an expression with all the unary operators one
after another?

In general, is it good programming practice to make use of the
precedence and associativity of operators?

Using precedence/associativity of operators when combining the
operators (probably) reduces the number of codelines (compared to
"spelling it out"), but doesn't it make the source code more difficult
to read?

Isn't it better to instead "spell it out"?

Another question, when would you use the unary operator sizeof with
other unary operators? To save code lines?

Quite a few questions, hmm, hope someone will be able to respond..!

BR!


Richard Heathfield 01-01-2007 10:27 PM

Re: Associativity of unary C Operators
 
dspfun said:

> I'm trying to get a good understanding of how unary operators work and
> have some questions about the following test snippets.
>
> int *p;
> ~!&*++p--;
> It doesn't compile, why?


Because ++ only works on objects, and the result of p-- is an expression,
but not an object. Other problems: p has no value, so p-- invokes undefined
behaviour. It points nowhere in particular, so even if ++p-- were
meaningful (which it is not), *++p-- would be dereferencing an
indeterminate pointer value - undefined behaviour again.

> int i = 10;
> ~!*&i++;
> It doesn't compile, why?


Because & only works on objects, and the result of p-- is an expression, but
not an object.

> int *p;
> ~!-&*p--;
> It doesn't compile, why?


Because unary minus only works on arithmetic types, and int * is not an
arithmetic type.

> The following does compile on the other hand:
> int *p;
> p = (int *) = 0x10101010; /*Just to set it to some value..*/


No, it doesn't. Drop the second =.

> ~!&*p--;
> p results in having the value 0x1010100c which I understand why.


The behaviour is undefined because p's value is changed to an invalid value.

> Is it possible to make an expression with all the unary operators one
> after another?


Probably not. What possible point could there be to it?

> In general, is it good programming practice to make use of the
> precedence and associativity of operators?


It is good programming practice to be aware of the precedence and
associativity characteristics of C, but to make a maintenance programmer's
job easier it is generally best to use parentheses rather than insist on
the maintainer knowing K&R2 p53 off by heart. It is, however, generally
considered necessary for all C programmers to be aware that multiplication
and division take precedence over addition and subtraction, however, so
there is no need to parenthesise the multiplication in v = a + b * c + d.

> Using precedence/associativity of operators when combining the
> operators (probably) reduces the number of codelines (compared to
> "spelling it out"), but doesn't it make the source code more difficult
> to read?


Yes.

> Isn't it better to instead "spell it out"?


Yes.

> Another question, when would you use the unary operator sizeof with
> other unary operators? To save code lines?


No. I don't generally think of "when would I use such-and-such an operator
with such-and-such another operator?". Each operator is a tool. I know when
I'd use a saw, and I know when I'd use a screwdriver, but the question
"when would I use a screwdriver with a saw?" doesn't really mean a lot.

Saving code lines as an end in itself is only ever a goal in IOCCC. Write
for clarity, not brevity.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.

Stephen Sprunk 01-02-2007 02:53 AM

Re: Associativity of unary C Operators
 
"dspfun" <dspfun@hotmail.com> wrote in message
news:1167688970.063126.304170@42g2000cwt.googlegro ups.com...
> In general, is it good programming practice to make use of the
> precedence and associativity of operators?
>
> Using precedence/associativity of operators when combining the
> operators (probably) reduces the number of codelines (compared to
> "spelling it out"), but doesn't it make the source code more difficult
> to read?
>
> Isn't it better to instead "spell it out"?


The general rule of thumb is that if you're forced to look at a
precedence table to figure out which operator goes first, you should add
parentheses to make it clear, which helps avoid mistakes.

> Another question, when would you use the unary operator sizeof with
> other unary operators? To save code lines?


Saving code lines should never be a goal; the goals are to make the code
(a) work correctly and (b) easy to maintain.

The primary audience for your code is other programmers; what the
compiler thinks of it is secondary. Write to the correct audience.

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking


--
Posted via a free Usenet account from http://www.teranews.com


Martin Ambuhl 01-02-2007 08:21 AM

Re: Associativity of unary C Operators
 
dspfun wrote:
> I'm trying to get a good understanding of how unary operators work and
> have some questions about the following test snippets.
>
> int *p;
> ~!&*++p--;
> It doesn't compile, why? The problem seems to be the ++, the compiler
> says: "Error: invalid l-value in increment".


Applying ++ to p-- is applying it to a value, not an object, but the ++
operator has a side effect which makes sense only when applied to a
modifiable object.

>
> int i = 10;
> ~!*&i++;
> It doesn't compile, why? The problem seems to be the ++, the compiler
> says: "Error: invalid l-value in unary "&"".


i++ is not an object: it has no address for the & operator to return.

[etc]



> In general, is it good programming practice to make use of the
> precedence and associativity of operators?


It is good programming practice to use operators only in contexts for
which they make sense. Why are writing arcane expressions like these
when you don't have a clue what the operators do?

dspfun 01-02-2007 04:11 PM

Re: Associativity of unary C Operators
 
Thanks for your repsonse! However, I'm not sure I follow what you mean,
please see below.

Richard Heathfield skrev:

> dspfun said:
>
> > I'm trying to get a good understanding of how unary operators work and
> > have some questions about the following test snippets.
> >
> > int *p;
> > ~!&*++p--;
> > It doesn't compile, why?

>
> Because ++ only works on objects, and the result of p-- is an expression,
> but not an object. Other problems: p has no value, so p-- invokes undefined
> behaviour. It points nowhere in particular, so even if ++p-- were
> meaningful (which it is not), *++p-- would be dereferencing an
> indeterminate pointer value - undefined behaviour again.


Expression = An expression in C is any valid combination of operators,
constants and variables.

As I understand your reasoning it's not possible to have multiple
operators in the same expression, but that is not true. Or am I
misunderstanding you?

Why does dereferencing p-- work, e.g. *p-- works. But ++p-- doesn't
work.

You say that ++ only works on objects, what is your definition of an
object C.

> > int i = 10;
> > ~!*&i++;
> > It doesn't compile, why?

>
> Because & only works on objects, and the result of p-- is an expression, but
> not an object.


Not sure I understan what you mean. What is your definition of an
object in C?

>
> > int *p;
> > ~!-&*p--;
> > It doesn't compile, why?

>
> Because unary minus only works on arithmetic types, and int * is not an
> arithmetic type.


Yes, thank you!


Richard Heathfield 01-02-2007 04:20 PM

Re: Associativity of unary C Operators
 
dspfun said:
> Richard Heathfield skrev:
>> dspfun said:
>>
>> > I'm trying to get a good understanding of how unary operators work and
>> > have some questions about the following test snippets.
>> >
>> > int *p;
>> > ~!&*++p--;
>> > It doesn't compile, why?

>>
>> Because ++ only works on objects, and the result of p-- is an expression,
>> but not an object. Other problems: p has no value, so p-- invokes
>> undefined behaviour. It points nowhere in particular, so even if ++p--
>> were meaningful (which it is not), *++p-- would be dereferencing an
>> indeterminate pointer value - undefined behaviour again.

>
> Expression = An expression in C is any valid combination of operators,
> constants and variables.


"An expression is a sequence of operators and operands that specifies
computation of a value, or that designates an object or a function, or that
generates side effects, or that performs a combination thereof."

> As I understand your reasoning it's not possible to have multiple
> operators in the same expression, but that is not true. Or am I
> misunderstanding you?


b + c * d is a legal expression with two operators, so you are
misunderstanding me.

>
> Why does dereferencing p-- work, e.g. *p-- works. But ++p-- doesn't
> work.


Because ++ takes as its operand an object with scalar type. The expression
p-- yields a value, not an object.

> You say that ++ only works on objects, what is your definition of an
> object C.


I don't have one, but the C Standard says:

* Object --- a region of data storage in the execution environment,
the contents of which can represent values. Except for bit-fields,
objects are composed of contiguous sequences of one or more bytes, the
number, order, and encoding of which are either explicitly specified
or implementation-defined.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.

dspfun 01-02-2007 04:25 PM

Re: Associativity of unary C Operators
 

Martin Ambuhl skrev:

> dspfun wrote:
> > I'm trying to get a good understanding of how unary operators work and
> > have some questions about the following test snippets.
> >
> > int *p;
> > ~!&*++p--;
> > It doesn't compile, why? The problem seems to be the ++, the compiler
> > says: "Error: invalid l-value in increment".

>
> Applying ++ to p-- is applying it to a value, not an object, but the ++
> operator has a side effect which makes sense only when applied to a
> modifiable object.


p-- is an expression. It is possible to do *p--. So we can use at least
some operators on expressions, that's probably why we have the
associativity rules.

I'm having problem understanding what you mean, probably because I
don't understand your definition of object and value?

In C I know of different types of variables, constants, pointers,
arrays and structs as well as enums.

> >
> > int i = 10;
> > ~!*&i++;
> > It doesn't compile, why? The problem seems to be the ++, the compiler
> > says: "Error: invalid l-value in unary "&"".

>
> i++ is not an object: it has no address for the & operator to return.


Same question as above, what is the defintion of an object?

> [etc]
>
>
>
> > In general, is it good programming practice to make use of the
> > precedence and associativity of operators?

>
> It is good programming practice to use operators only in contexts for
> which they make sense. Why are writing arcane expressions like these
> when you don't have a clue what the operators do?


That's the reason why I'm writing arcane expressions like this; to
grasp a solid understanding of what the operators are doing to its
operands and how the operators can be used.

Thanks for your response!!


dspfun 01-02-2007 05:32 PM

Re: Associativity of unary C Operators
 

> > Why does dereferencing p-- work, e.g. *p-- works. But ++p-- doesn't
> > work.

>
> Because ++ takes as its operand an object with scalar type. The expression
> p-- yields a value, not an object.


So why does it work when you split ++p-- in two different lines?:
p--;
++p;

You'll probably say the same thing again, but what is the main
difference when splitting the expression in two?

Thanks again for your response!!


John Bode 01-02-2007 05:55 PM

Re: Associativity of unary C Operators
 

dspfun wrote:
> Martin Ambuhl skrev:
>
> > dspfun wrote:
> > > I'm trying to get a good understanding of how unary operators work and
> > > have some questions about the following test snippets.
> > >
> > > int *p;
> > > ~!&*++p--;
> > > It doesn't compile, why? The problem seems to be the ++, the compiler
> > > says: "Error: invalid l-value in increment".

> >
> > Applying ++ to p-- is applying it to a value, not an object, but the ++
> > operator has a side effect which makes sense only when applied to a
> > modifiable object.

>
> p-- is an expression. It is possible to do *p--. So we can use at least
> some operators on expressions, that's probably why we have the
> associativity rules.


The ++ and -- operators require that their operands are lvalues;
lvalues are expressions that refer to a region of memory such that the
memory can be read or modified. In other words, ++ and -- only modify
objects in memory.

For example, given the following code fragment:

int i = 2;
int *p = &i;
int j = *p++;

The expressions i, j, and p are all lvalues; they all refer to a region
of memory that can be read and modified. The integer constant
expression 2 is not an lvalue. It does not refer to a region of
memory, so an expression like 2++ would not make sense, since there's
nothing to apply the side effect to.

The result of an autoincrement or autodecrement expression is a value,
not an lvalue; for example, given the code above, the result of the
expression --i would be 1, which is not an lvalue. So writing the
expression --i++ would be equivalent to writing 1++, which, again, is
nonsensical.

So what about expressions like *p++? The indirection operator doesn't
require that its operand be an lvalue, because it's not attempting to
modify a region of memory directly. Assuming that the value stored in
p is 0x8000, the result of the expression p++ is the *value* 0x8000,
and the dereference operator is applied to that value.

>
> I'm having problem understanding what you mean, probably because I
> don't understand your definition of object and value?
>


An object has a specific location in memory. A value doesn't.

> In C I know of different types of variables, constants, pointers,
> arrays and structs as well as enums.
>
> > >
> > > int i = 10;
> > > ~!*&i++;
> > > It doesn't compile, why? The problem seems to be the ++, the compiler
> > > says: "Error: invalid l-value in unary "&"".

> >
> > i++ is not an object: it has no address for the & operator to return.

>
> Same question as above, what is the defintion of an object?
>
> > [etc]
> >
> >
> >
> > > In general, is it good programming practice to make use of the
> > > precedence and associativity of operators?

> >
> > It is good programming practice to use operators only in contexts for
> > which they make sense. Why are writing arcane expressions like these
> > when you don't have a clue what the operators do?

>
> That's the reason why I'm writing arcane expressions like this; to
> grasp a solid understanding of what the operators are doing to its
> operands and how the operators can be used.
>
> Thanks for your response!!



Richard Heathfield 01-02-2007 06:45 PM

Re: Associativity of unary C Operators
 
dspfun said:

>
>> > Why does dereferencing p-- work, e.g. *p-- works. But ++p-- doesn't
>> > work.

>>
>> Because ++ takes as its operand an object with scalar type. The
>> expression p-- yields a value, not an object.

>
> So why does it work when you split ++p-- in two different lines?:
> p--;
> ++p;


p-- decrements p, and yields as its result the old >>>*value*<<< of p, NOT
the p object itself. For example, if p points to an int at address
0x1234ABCD, then p-- yields the >>>*value*<<< 0x1234ABCD (and, as a side
effect, adjusts the value of p). ++0x1234ABCD makes no sense, so ++p--
doesn't make sense.

But ++p; means "yield as your result the new value of p and, as a side
effect, adjust the value of p". ++, in this case, is being applied to p,
whereas in the (illegal) case of ++p--, you are trying to apply ++ not to p
but to the value that results from evaluating the expression p--.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.


All times are GMT. The time now is 10:12 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.