A couple questions

Discussion in 'C Programming' started by Snis Pilbor, Jul 27, 2006.

  1. Snis Pilbor

    Snis Pilbor Guest

    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.
     
    Snis Pilbor, Jul 27, 2006
    #1
    1. Advertising

  2. On 2006-07-27, 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);
    > 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
     
    Andrew Poelstra, Jul 27, 2006
    #2
    1. Advertising

  3. Snis Pilbor

    Eric Sosman Guest

    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.

    > What about sequence points?


    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.

    --
     
    Eric Sosman, Jul 27, 2006
    #3
  4. On Thu, 27 Jul 2006, Andrew Poelstra wrote:

    > On 2006-07-27, Snis Pilbor <> 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
     
    Tak-Shing Chan, Jul 27, 2006
    #4
  5. Snis Pilbor

    Flash Gordon Guest

    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
    clear to subsequent human readers.

    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
     
    Flash Gordon, Jul 27, 2006
    #5
  6. 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.

    > What about sequence points?


    ',' 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
    CPU's load-effective-address operation.

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Jul 27, 2006
    #6
  7. Snis Pilbor

    Chris Torek Guest

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


    In article <-gordon.me.uk>,
    Flash Gordon <> 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
    >clear to subsequent human readers.
    >
    >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
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Jul 28, 2006
    #7
  8. Andrew Poelstra <> 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.
     
    Christopher Benson-Manica, Jul 28, 2006
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Wayne  Wengert

    A Couple of Questions

    Wayne Wengert, Jan 22, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    336
    =?Utf-8?B?aSBkb250IGtub3cgbXVjaCBhYm91dCB2cy4uLmI=
    Jan 22, 2004
  2. Martin

    A Couple Of Questions

    Martin, Mar 6, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    361
    Mark Jerde
    Mar 6, 2004
  3. =?Utf-8?B?UnVkeQ==?=

    Couple of questions

    =?Utf-8?B?UnVkeQ==?=, Dec 27, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    330
    =?Utf-8?B?UnVkeQ==?=
    Dec 27, 2004
  4. =?Utf-8?B?U2NjcjE4?=

    Couple of easy questions

    =?Utf-8?B?U2NjcjE4?=, Jun 22, 2005, in forum: ASP .Net
    Replies:
    4
    Views:
    414
    =?Utf-8?B?U2NjcjE4?=
    Jun 22, 2005
  5. Ali Syed
    Replies:
    3
    Views:
    582
    Mark McIntyre
    Oct 13, 2004
Loading...

Share This Page