Velocity Reviews > A couple questions

# A couple questions

Snis Pilbor
Guest
Posts: n/a

 07-27-2006
Hello,

First question: besides the syntactical difference of one having
to be enclosed in brackets in some situations, are there any subtler
differences between (say)
x=(some expression), y=(some expression);
and
x=(some expression); y=(some expression); ?

What about sequence points? For example, would the phrase "i++, i++;"
be well-defined? Is there any guarantee about which computation the
program will perform first, for example is "x=x+1, x=x*2;" a
well-defined phrase? (intuitively I would assume so and that it would
go left to right but I'd like to be sure)

Second question: in one project I maintain, the guy is fond of
using >> and << for routine division/multiplication. For instance
instead of size *= 2, he will write size <<= 1. My question is, is
there a practical reason for doing this, for routine situations besides
actual bit twiddling? I know << is usually faster than *, but I always
assumed any compiler worth a hill of beans would easily know to
optimize something like "size *= 2" as much as possible anyway?

Thanks for helping out, you guys rock =)

-Snis P.

Andrew Poelstra
Guest
Posts: n/a

 07-27-2006
On 2006-07-27, Snis Pilbor <(E-Mail Removed)> wrote:
> Hello,
>
> First question: besides the syntactical difference of one having
> to be enclosed in brackets in some situations, are there any subtler
> differences between (say)
> x=(some expression), y=(some expression);
> and
> x=(some expression); y=(some expression); ?
>

Well, the first is a single expression returning the value of y. The
second is two separate expressions and can't be used as, say,
c = (x=a, y=b); which gives c the value of b.

> What about sequence points? For example, would the phrase "i++, i++;"
> be well-defined? Is there any guarantee about which computation the
> program will perform first, for example is "x=x+1, x=x*2;" a
> well-defined phrase? (intuitively I would assume so and that it would
> go left to right but I'd like to be sure)

I believe that it is well-defined. However, I don't think that the order
of computations is guaranteed. I don't claim to be an expert, though, so
you should wait for a more knowledgable person to answer.

I do know, however, that most well-written code shouldn't care what the
order of computations is, because a maintenance programmer shouldn't be
expected to know. Well-written code should be clear and be evaluated in
one (obvious) way.

> Second question: in one project I maintain, the guy is fond of
> using >> and << for routine division/multiplication. For instance,
> instead of size *= 2, he will write size <<= 1. My question is, is
> there a practical reason for doing this, for routine situations besides
> actual bit twiddling?

Tsk, tsk, tsk. There is no reason for that, except to make the code
unreadable. Tomorrow I might want to multiply by 12 instead of 8; with
multiplication that involves changing one number.

y *= 8; /* In the case that the grommet fails to widge consistently,
multiply by 13 to compensate. Shouldn't be an issue with
the new vendor, though. */
x <<= 2; /* If we're interfacing with DeviceBoy revision F, we need to
shift by 4 to make room for the LCD brightness flags. We
should be compatible before the next version ships. */

See how using an inappropriate operator would make maintenance more
difficult? You should correct your errant colleague.

> I know << is usually faster than *

No you don't.

> , but I always
> assumed any compiler worth a hill of beans would easily know to
> optimize something like "size *= 2" as much as possible anyway?
>

Indeed it will.

> Thanks for helping out, you guys rock =)
>

No problem.

--
Andrew Poelstra <website down>
To reach my email, use <email also down>
New server ETA: 1 days

Eric Sosman
Guest
Posts: n/a

 07-27-2006

Snis Pilbor wrote On 07/27/06 14:49,:
> Hello,
>
> First question: besides the syntactical difference of one having
> to be enclosed in brackets in some situations, are there any subtler
> differences between (say)
> x=(some expression), y=(some expression);
> and
> x=(some expression); y=(some expression); ?

Well, you can throw parentheses around the first one
(not enclosing the semicolon) and use it as part of a
still larger expression:

z = (x = some_expression, y = some_expression) + 42;

.... which you could not do with a pair of complete statements.

There are sequence points at the comma and at the
semicolons.

For example, would the phrase "i++, i++;"
> be well-defined?

Yes.

> Is there any guarantee about which computation the
> program will perform first, for example is "x=x+1, x=x*2;" a
> well-defined phrase? (intuitively I would assume so and that it would
> go left to right but I'd like to be sure)

You assume correctly. However, the fact that you find it
necessary to assume is troubling; *all* this stuff should be
in your C textbook or reference or whatever. If you don't
have such a thing, you should.

> Second question: in one project I maintain, the guy is fond of
> using >> and << for routine division/multiplication.

Oh, no! Again? Didn't we just *do* this? Didn't we just
do this for the umpteenth time? Go Google it: just pick any
ten threads at random and you'll have a better-than-even chance
of seeing this particular Apple of Discord on one or another of
its all-too-frequent trips down the table.

--
http://www.velocityreviews.com/forums/(E-Mail Removed)

Tak-Shing Chan
Guest
Posts: n/a

 07-27-2006
On Thu, 27 Jul 2006, Andrew Poelstra wrote:

> On 2006-07-27, Snis Pilbor <(E-Mail Removed)> wrote:
>> What about sequence points? For example, would the phrase "i++, i++;"
>> be well-defined? Is there any guarantee about which computation the
>> program will perform first, for example is "x=x+1, x=x*2;" a
>> well-defined phrase? (intuitively I would assume so and that it would
>> go left to right but I'd like to be sure)

>
> I believe that it is well-defined. However, I don't think that the order
> of computations is guaranteed. I don't claim to be an expert, though, so

The order is guaranteed. However, be careful not to confuse
the comma operator with comma-separated lists.

Tak-Shing

Flash Gordon
Guest
Posts: n/a

 07-27-2006
Snis Pilbor wrote:
> Hello,
>
> First question: besides the syntactical difference of one having
> to be enclosed in brackets in some situations, are there any subtler
> differences between (say)
> x=(some expression), y=(some expression);

The above returns a value. So you could do:
z = x=(some expression), y=(some expression);

> and
> x=(some expression); y=(some expression); ?

Obviously this is different.

> What about sequence points? For example, would the phrase "i++, i++;"
> be well-defined? Is there any guarantee about which computation the
> program will perform first, for example is "x=x+1, x=x*2;" a
> well-defined phrase? (intuitively I would assume so and that it would
> go left to right but I'd like to be sure)

The comma operator (as opposed to the comma used to separate arguments
passed to a function) is a sequence point and guarantees the left
argument is evaluated first.

> Second question: in one project I maintain, the guy is fond of
> using >> and << for routine division/multiplication. For instance
> instead of size *= 2, he will write size <<= 1. My question is, is
> there a practical reason for doing this, for routine situations besides
> actual bit twiddling? I know << is usually faster than *, but I always
> assumed any compiler worth a hill of beans would easily know to
> optimize something like "size *= 2" as much as possible anyway?

Many years ago there was sometimes an advantage. However, for a long
time compilers have been intelligent enough to use a shift where it is
appropriate (sometimes doing a multiply will be faster).

Using a shift, on the other hand, has a number of disadvantages. Right
shifting a negative number will not do a division by a power of two on
*all* systems. Shifting when you intend multiplication/division is less

So I would *always* use multiplication or division when that is what I
mean unless it is *proved* to be a problem in that specific instance.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc

Andrey Tarasevich
Guest
Posts: n/a

 07-27-2006
Snis Pilbor wrote:
> ...
> First question: besides the syntactical difference of one having
> to be enclosed in brackets in some situations, are there any subtler
> differences between (say)
> x=(some expression), y=(some expression);
> and
> x=(some expression); y=(some expression); ?

Assuming that both are complete statements (they end in ';' in your example),
there's no difference between the two.

',' operator produces a sequence point, so there's no problem here.

> For example, would the phrase "i++, i++;"
> be well-defined?

Yes.

> Is there any guarantee about which computation the
> program will perform first, for example is "x=x+1, x=x*2;" a
> well-defined phrase?

The left-hand side is evaluated first. As dictated by the sequence point, all
side-effects of the LHS take place before the evaluation of RHS begins.

> (intuitively I would assume so and that it would
> go left to right but I'd like to be sure)

That's indeed how it would go.

> Second question: in one project I maintain, the guy is fond of
> using >> and << for routine division/multiplication. For instance
> instead of size *= 2, he will write size <<= 1. My question is, is
> there a practical reason for doing this, for routine situations besides
> actual bit twiddling?

No, no reason (unless you are using a really weird compiler).

Also note that for negative left operand ('size') the effects of 'size >> 1' and
'size / 2' are not necessarily identical. In C90 both are
implementation-defined. In C99 the latter is required to round toward 0, while
the former is still implementation-defined.

> I know << is usually faster than *,

No. '<<' and '*' are C language operators. The notion of 'speed' is not
applicable to them. Apparently, you are identifying these operators with
"similar" CPU instructions of you favorite hardware platform (say, 'shl' and
'mul'), believing that there's a 1:1 match between them. This is not correct in
general case. When it comes to such simple expressions, modern compilers usually
easily recognize equivalent expressions and generate identical (optimal) machine
instructions for them, i.e. 'size *= 2' and 'size <<= 1' will normally produce
the same code and give you the same efficiency. What often comes as a surprise
to such manual-optimization fans is that the most optimal code for both 'size *=
2' and 'size <<= 1' does not use neither CPU's multiply operation nor CPU's
shift operation, but instead uses something much less obvious, like some form of

--
Best regards,
Andrey Tarasevich

Chris Torek
Guest
Posts: n/a

 07-28-2006
>Snis Pilbor wrote:
>> ... are there any subtler differences between (say)
>> x=(some expression), y=(some expression);

In article <(E-Mail Removed)-gordon.me.uk>,
Flash Gordon <(E-Mail Removed)> wrote:
>The above returns a value. So you could do:
>z = x=(some expression), y=(some expression);

Yes -- but note that:

z = x = 4, y = 5;

parses as:

(z = (x = 4)), (y = 5);

since the "=" operator binds more tightly than the "," operator.

>> and x=(some expression); y=(some expression); ?

>Obviously this is different.

In this case, it would give the same result:

z = x = 4; y = 5;

still sets both z and x to 4, and y to 5.

>> What about sequence points? ...

>The comma operator (as opposed to the comma used to separate arguments
>passed to a function) is a sequence point and guarantees the left
>argument is evaluated first.

Yes. However, if (x = 4, y = 5) is parenthesized and the entire
thing is put into a larger expression, one can obtain undefined
behavior:

x = x + (x = 4, y = 5); /* undefined */

The version with the semicolons is not an expression, so it cannot
be parenthesized and used as one.

>> Second question: in one project I maintain, the guy is fond of
>> using >> and << for routine division/multiplication. ...

>Many years ago there was sometimes an advantage. However, for a long
>time compilers have been intelligent enough to use a shift where it is
>appropriate (sometimes doing a multiply will be faster).

Even Dennis Ritchie's original PDP-11 C compiler would turn "x *
constant-power-of-2" into "x << log2(that)", if I remember right.
Modern compilers are pretty good at this; "x = (x * 10) + (c -
'0')" turns into a pair of non-obvious VAX instructions under GCC:

# if x is in r3 and c is in r2
moval r3[r3], r3
movaw -48(r2)[r3], r3

>Using a shift, on the other hand, has a number of disadvantages. Right
>shifting a negative number will not do a division by a power of two on
>*all* systems. Shifting when you intend multiplication/division is less
>
>So I would *always* use multiplication or division when that is what I
>mean unless it is *proved* to be a problem in that specific instance.

You can also help out the compiler by using "unsigned" if the value
will never be negative:

unsigned int x;
...
x /= 32;

usually allows the compiler to emit "x >>= 5" internally, because
here a shift *does* give the same answer as a divide.

(GCC will still replace divides when appropriate: some turn into
shift-and-fix-up, others turn into reciprocal multiply.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
Reading email is like searching for food in the garbage, thanks to spammers.

Christopher Benson-Manica
Guest
Posts: n/a

 07-28-2006
Andrew Poelstra <(E-Mail Removed)> wrote:

(WRT to x=x+1, x=x*2

> I believe that it is well-defined. However, I don't think that the order
> of computations is guaranteed. I don't claim to be an expert, though, so
> you should wait for a more knowledgable person to answer.

You are correct on the first point; however, the order of computations
is guaranteed, at least per 6.5.17 of n869:

"The left operand of a comma operator is evaluated as a void expression;
there is a sequence point after its evaluation. Then the right operand is
evaluated; the result has its type and value."

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.