the loop control

Discussion in 'C Programming' started by Joe keane, Oct 29, 2011.

  1. Joe keane

    Joe keane Guest

    Which is better?

    int fa(int fool, struct foo *foob)
    {
    int ct;
    struct foo *foop;

    ...

    ct = fool;
    foop = foob;

    while (--ct >= 0)
    {
    ...(foop)
    foop++;
    }

    ...
    }

    int fb(int fool, struct foo *foob)
    {
    struct foo *foop;
    struct foo *fooe;

    ...

    foop = foob;
    fooe = foob + fool;

    while (foop < fooe)
    {
    ...(foop)
    foop++;
    }

    ...
    }
    Joe keane, Oct 29, 2011
    #1
    1. Advertising

  2. Joe keane

    Ian Collins Guest

    On 10/30/11 10:38 AM, Joe keane wrote:
    > Which is better?


    Start by defining better!

    > int fa(int fool, struct foo *foob)
    > {
    > int ct;
    > struct foo *foop;
    >
    > ...
    >
    > ct = fool;
    > foop = foob;
    >
    > while (--ct>= 0)
    > {
    > ...(foop)
    > foop++;
    > }
    >
    > ...
    > }
    >
    > int fb(int fool, struct foo *foob)
    > {
    > struct foo *foop;
    > struct foo *fooe;
    >
    > ...
    >
    > foop = foob;
    > fooe = foob + fool;
    >
    > while (foop< fooe)
    > {
    > ...(foop)
    > foop++;
    > }
    >
    > ...
    > }



    --
    Ian Collins
    Ian Collins, Oct 29, 2011
    #2
    1. Advertising

  3. Joe keane

    Kaz Kylheku Guest

    On 2011-10-29, Joe keane <> wrote:
    > Which is better?


    Neither. Firstly, you're neglecting to take advantage of parameters being
    local variables. Do you need fool and foob to retain the values
    they had on entry into the function?

    int fa(int fool, struct foo *foob)
    {
    while (fool-- > 0) {
    /* process object referenced by foob */
    foob++;
    }
    }

    > while (--ct >= 0)


    Getting into the habit of coding a descending loop this way will bite
    you if the loop counter is ever an unsigned type. (Hopefully a compiler will
    warn you that the comparison is always true because of the range of the type.)

    If you're going to introduce an extra integer index variable anyway, consider
    array indexing.

    for (ct = 0; ct < fool; ct++) {
    ... foob ...
    }

    This way you avoid introducing an extra pointer just to keep your
    foob pointer stable.

    If this array of struct foo is used frequently in the program,
    you might want to encapsulate it better, so you don't have to keep
    passing two parameters everywhere just to represent one object.

    A null-terminated array is a another possibility. This is like
    a null-terminated string, but of course the null element is a pointer.
    The argument array passed into main is this way.

    int fa(struct foo *foob)
    {
    for (; *foob != NULL; foob++) {
    /* process foob */
    }
    }
    Kaz Kylheku, Oct 29, 2011
    #3
  4. Joe keane

    Joe Pfeiffer Guest

    (Joe keane) writes:

    > Which is better?


    <snip>

    No.
    Joe Pfeiffer, Oct 30, 2011
    #4
  5. Joe keane

    Philip Lantz Guest

    On Sat, 29 Oct 2011, Joe keane wrote:

    > Which is better?
    >
    > ...


    int fc(int fool, struct foo *foob)
    {
    ...

    for (int i = 0; i < fool; i++)
    {
    ...(foob)
    }

    ...
    }
    Philip Lantz, Oct 30, 2011
    #5
  6. Joe keane

    Joe keane Guest

    In article <>,
    Kaz Kylheku <> wrote:
    >Firstly, you're neglecting to take advantage of parameters being
    >local variables.


    I don't like that "feature" of C.

    It's harder to debug, it's harder to maintain.

    >Do you need fool and foob to retain the values they had on entry into
    >the function?


    It helps to retain sanity.

    e.g.

    int f2(int len, struct foo *fob)
    {
    ...

    for (j = 0; j < len; j++)
    {
    fob->a = fq(...);
    fob++;
    }

    ...

    for (j = 0; j < len; j++)
    {
    fob->b = fr(...);
    fob++;
    }

    ...
    }

    Oops!
    Joe keane, Oct 31, 2011
    #6
  7. Joe keane

    James Kuyper Guest

    On 10/31/2011 11:21 AM, Joe keane wrote:
    > In article <>,
    > Kaz Kylheku <> wrote:
    >> Firstly, you're neglecting to take advantage of parameters being
    >> local variables.

    >
    > I don't like that "feature" of C.
    >
    > It's harder to debug, it's harder to maintain.
    >
    >> Do you need fool and foob to retain the values they had on entry into
    >> the function?

    >
    > It helps to retain sanity.
    >
    > e.g.
    >
    > int f2(int len, struct foo *fob)
    > {
    > ...
    >
    > for (j = 0; j < len; j++)
    > {
    > fob->a = fq(...);
    > fob++;
    > }
    >
    > ...
    >
    > for (j = 0; j < len; j++)
    > {
    > fob->b = fr(...);
    > fob++;
    > }
    >
    > ...
    > }
    >
    > Oops!


    I agree; that's a context where you need to keep the original value of
    fob. To get compiler enforcement of the idea that it should not be done,
    declare fob to as "struct foo * const fob".

    However, I don't see anything wrong with

    int f2(int len, struct foo *fob)
    {
    while(len--)
    {
    fob->a = fq(...);
    fob++;
    }
    }

    I don't see that as being any harder to debug, any harder to maintain,
    and I don't see it as being necessary to retain my sanity (though some
    would undoubtedly argue that it's too late for me to worry about that :) ).
    James Kuyper, Oct 31, 2011
    #7
  8. Joe keane

    Joe keane Guest

    compare

    int fc(int len, struct foo *fob, struct bar *bab)
    {
    ...

    for (j = 0; j < len; j++)
    {
    fob[j].a = bab[j].x;
    fob[j].b = bab[j].y + 1;
    fob[j].c = bab[j].d;
    }

    ...
    }

    versus

    int fd(int len, struct foo *fob, struct bar *bab)
    {
    ...

    for (j = 0; j < len; j++)
    {
    fop = &fob[j];
    bap = &bab[j];
    fop->a = bap->x;
    fop->b = bap->y + 1;
    fop->c = bap->d;
    }

    ...
    }

    The first one looks like Pascal or Fortran. The second one looks more
    like C. It says 'i don't need the array base and index, just give me
    the pointer'.

    All style, you should get the same machine code. But i've seen too many
    cases where the code that looks 'faster' actually is! I mean it's nice
    to say 'the optimizer will take care of this', but then it doesn't hurt
    to help it some, by not making code more complicated than it should be.

    Anyway readability is key; to me code like

    ct = len;
    fop = fob;
    while (--ct >= 0)
    {
    ...(fop)
    fop++;
    }

    is so idiomatic that it's easiest.
    Joe keane, Oct 31, 2011
    #8
  9. Joe keane

    Seebs Guest

    On 2011-10-31, Joe keane <> wrote:
    > In article <>,
    > Kaz Kylheku <> wrote:
    >>Firstly, you're neglecting to take advantage of parameters being
    >>local variables.


    > I don't like that "feature" of C.


    > It's harder to debug, it's harder to maintain.


    It doesn't matter. It's there. If you write code which acts like it's
    not, it sends up big red flags for any future maintainer of your code.

    -s
    --
    Copyright 2011, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 31, 2011
    #9
  10. Joe keane

    jgharston Guest

    James Kuyper wrote:
    > Kaz Kylheku wrote:
    > > Firstly, you're neglecting to take advantage of parameters being
    > > local variables.

    > I don't like that "feature" of C.


    It's not a feature of C, it's a feature of subroutines.
    I can't think of any programming language where the
    passed parameters are not local to the subroutine.

    I'm happy for somebody to enlighten me, though.

    JGH
    jgharston, Oct 31, 2011
    #10
  11. Joe keane

    Seebs Guest

    On 2011-10-31, jgharston <> wrote:
    > James Kuyper wrote:
    >> Kaz Kylheku wrote:
    >> > Firstly, you're neglecting to take advantage of parameters being
    >> > local variables.

    >> I don't like that "feature" of C.


    > It's not a feature of C, it's a feature of subroutines.
    > I can't think of any programming language where the
    > passed parameters are not local to the subroutine.


    At least some Fortrans. Everything was passed by reference, and yes,
    this meant that if you called a routine that modified a parameter with
    a constant, the constant might get changed.

    -s
    --
    Copyright 2011, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 31, 2011
    #11
  12. Joe keane

    Sjouke Burry Guest

    jgharston <> wrote in news:c173def7-db03-4bf0-adf5-
    :

    > James Kuyper wrote:
    >> Kaz Kylheku wrote:
    >> > Firstly, you're neglecting to take advantage of parameters being
    >> > local variables.

    >> I don't like that "feature" of C.

    >
    > It's not a feature of C, it's a feature of subroutines.
    > I can't think of any programming language where the
    > passed parameters are not local to the subroutine.
    >
    > I'm happy for somebody to enlighten me, though.
    >
    > JGH
    >


    Ever heard of FORTRAN?
    Sjouke Burry, Oct 31, 2011
    #12
  13. Joe keane

    James Kuyper Guest

    On 10/31/2011 01:27 PM, jgharston wrote:
    > James Kuyper wrote:
    >> Kaz Kylheku wrote:
    >>> Firstly, you're neglecting to take advantage of parameters being
    >>> local variables.

    >> I don't like that "feature" of C.


    I didn't write that last sentence; it was written by Joe Keane. You need
    to fix up your quoting system.

    > It's not a feature of C, it's a feature of subroutines.


    It's a feature of C subroutines; there are other languages that do not
    share that feature.

    > I can't think of any programming language where the
    > passed parameters are not local to the subroutine.


    See <http://en.wikipedia.org/wiki/Evaluation_strategy>; C's
    call-by-reference approach is far from being universal. With most of the
    other strategies, it would be a bad idea to treat a function parameter
    as a local variable.
    James Kuyper, Oct 31, 2011
    #13
  14. Joe keane

    Kaz Kylheku Guest

    On 2011-10-31, Joe keane <> wrote:
    > In article <>,
    > Kaz Kylheku <> wrote:
    >>Firstly, you're neglecting to take advantage of parameters being
    >>local variables.

    >
    > I don't like that "feature" of C.


    This feature is found in other languages.

    (defun lisp-function (arg)
    (incf arg))

    > It's harder to debug, it's harder to maintain.


    This sort of statement is impossible to justify without a lot of
    qualifications. Undoubtedly whenever you modify *any* variable, be it
    a by-value argument or not, you can create bugs. (Just ask any proponent of
    functional languages.)

    The trick of destructively manipulating by-value arguemnts keeps
    small and simple functions small and simple, where extra variables
    might just create clutter.

    Everything you add to the function, some maintainer will have to suspect was
    done for a significant reason beyond mere style.

    >>Do you need fool and foob to retain the values they had on entry into
    >>the function?

    >
    > It helps to retain sanity.


    N
    > e.g.
    >
    > int f2(int len, struct foo *fob)
    > {
    > ...
    >
    > for (j = 0; j < len; j++)
    > {
    > fob->a = fq(...);
    > fob++;
    > }
    >
    > ...
    >
    > for (j = 0; j < len; j++)
    > {
    > fob->b = fr(...);
    > fob++;
    > }
    >
    > ...
    > }
    >
    > Oops!


    This function suggests to me that it is two functions combined into one.

    Or, possibly, that the separate loop bodies can be combined into a single pass.

    If there is no need for two passes, then the above code wastes my time
    trying to confirming a suspicion that there have to be two passes,
    because I respect the intelligence of the prior coder and assume he or
    she did things for a good reason.

    Thus if the following is a correct rewrite, then it is better:

    for (j = 0; j < len; j++)
    {
    fob->a = fq(...);
    fob->b = fr(...);
    fob++;
    }
    Kaz Kylheku, Oct 31, 2011
    #14
  15. Joe keane

    Kaz Kylheku Guest

    On 2011-10-31, Joe keane <> wrote:
    > Anyway readability is key; to me code like
    >
    > ct = len;
    > fop = fob;
    > while (--ct >= 0)
    > {
    > ...(fop)
    > fop++;
    > }
    >
    > is so idiomatic that it's easiest.


    As pointed out upthread, it's an infinite loop should ct ever happen
    to be unsigned. Learning disability?

    C programmers who know what they are donig rarely use predecrement like this in
    descending loops, because the counter decrements even in the case that the loop
    guard fails and the body is not to be executed any more, which means that it
    decrements one past zero.
    Kaz Kylheku, Oct 31, 2011
    #15
  16. Joe keane

    Ben Pfaff Guest

    Kaz Kylheku <> writes:

    > On 2011-10-31, Joe keane <> wrote:
    >> Anyway readability is key; to me code like
    >>
    >> ct = len;
    >> fop = fob;
    >> while (--ct >= 0)
    >> {
    >> ...(fop)
    >> fop++;
    >> }
    >>
    >> is so idiomatic that it's easiest.

    >
    > As pointed out upthread, it's an infinite loop should ct ever happen
    > to be unsigned. Learning disability?


    It seems likely to me that the compiler would warn that the loop
    condition cannot ever be true.
    --
    char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
    ={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
    =b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
    2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
    Ben Pfaff, Oct 31, 2011
    #16
  17. Joe keane

    James Kuyper Guest

    On 10/31/2011 03:38 PM, Ben Pfaff wrote:
    > Kaz Kylheku <> writes:
    >
    >> On 2011-10-31, Joe keane <> wrote:
    >>> Anyway readability is key; to me code like
    >>>
    >>> ct = len;
    >>> fop = fob;
    >>> while (--ct >= 0)
    >>> {
    >>> ...(fop)
    >>> fop++;
    >>> }
    >>>
    >>> is so idiomatic that it's easiest.

    >>
    >> As pointed out upthread, it's an infinite loop should ct ever happen
    >> to be unsigned. Learning disability?

    >
    > It seems likely to me that the compiler would warn that the loop
    > condition cannot ever be true.


    "true" => "false".

    A compiler that warns whenever a loop condition can never be false would
    annoy those people who rely upon the while(1) idiom.
    James Kuyper, Oct 31, 2011
    #17
  18. Joe keane

    Ben Pfaff Guest

    James Kuyper <> writes:

    > On 10/31/2011 03:38 PM, Ben Pfaff wrote:
    >> Kaz Kylheku <> writes:
    >>
    >>> On 2011-10-31, Joe keane <> wrote:
    >>>> Anyway readability is key; to me code like
    >>>>
    >>>> ct = len;
    >>>> fop = fob;
    >>>> while (--ct >= 0)
    >>>> {
    >>>> ...(fop)
    >>>> fop++;
    >>>> }
    >>>>
    >>>> is so idiomatic that it's easiest.
    >>>
    >>> As pointed out upthread, it's an infinite loop should ct ever happen
    >>> to be unsigned. Learning disability?

    >>
    >> It seems likely to me that the compiler would warn that the loop
    >> condition cannot ever be true.

    >
    > "true" => "false".
    >
    > A compiler that warns whenever a loop condition can never be false would
    > annoy those people who rely upon the while(1) idiom.


    The compiler is smarter than that (I see that it isn't actually
    specific to loop conditionals):

    blp@blp:~/nicira/openflow(0)$ cat foo.c
    int
    main(void)
    {
    unsigned x = 5;
    while (--x >= 0) {
    ;
    }
    while (1) {
    ;
    }
    return 0;
    }
    blp@blp:~/nicira/openflow(0)$ gcc -Wall -Wextra foo.c
    foo.c: In function 'main':
    foo.c:5: warning: comparison of unsigned expression >= 0 is always true
    blp@blp:~/nicira/openflow(0)$

    --
    "To get the best out of this book, I strongly recommend that you read it."
    --Richard Heathfield
    Ben Pfaff, Oct 31, 2011
    #18
  19. jgharston <> writes:
    > James Kuyper wrote:
    >> Kaz Kylheku wrote:
    >> > Firstly, you're neglecting to take advantage of parameters being
    >> > local variables.

    >> I don't like that "feature" of C.

    >
    > It's not a feature of C, it's a feature of subroutines.
    > I can't think of any programming language where the
    > passed parameters are not local to the subroutine.
    >
    > I'm happy for somebody to enlighten me, though.


    It's a feature of C.

    Another example: in Ada, parameters (unless they're marked "in out" or
    "out") are local to the subroutine, but they're constant (read-only).
    If you try to assign a value to a parameter, the compiler will complain.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Oct 31, 2011
    #19
  20. Joe keane

    Phil Carmody Guest

    (Joe keane) writes:
    > In article <>,
    > Kaz Kylheku <> wrote:
    > >Firstly, you're neglecting to take advantage of parameters being
    > >local variables.

    >
    > I don't like that "feature" of C.
    >
    > It's harder to debug, it's harder to maintain.
    >
    > >Do you need fool and foob to retain the values they had on entry into
    > >the function?

    >
    > It helps to retain sanity.
    >
    > e.g.
    >
    > int f2(int len, struct foo *fob)
    > {
    > ...
    >
    > for (j = 0; j < len; j++)
    > {
    > fob->a = fq(...);
    > fob++;
    > }
    >
    > ...
    >
    > for (j = 0; j < len; j++)
    > {
    > fob->b = fr(...);
    > fob++;
    > }
    >
    > ...
    > }
    >
    > Oops!


    Needing to use something more than once, where use modifies that
    thing, clearly requires you to maintain an unmodified copy of the
    original.

    Needing to use something once, where use modifies that thing, clearly
    does not require you to maintain an unmodified copy of the original.

    If you are unable to see the difference between these cases, then you
    will clearly be hampered when it comes to chosing appropriate coding
    techniques. That, however, is your problem, and not the language's
    problem.

    Phil
    --
    Unix is simple. It just takes a genius to understand its simplicity
    -- Dennis Ritchie (1941-2011), Unix Co-Creator
    Phil Carmody, Oct 31, 2011
    #20
    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. =?Utf-8?B?VGltOjouLg==?=

    Loop the loop...

    =?Utf-8?B?VGltOjouLg==?=, Feb 16, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    1,379
    Karl Seguin
    Feb 16, 2005
  2. Steven

    while loop in a while loop

    Steven, Mar 24, 2005, in forum: Java
    Replies:
    5
    Views:
    2,230
    Tim Slattery
    Mar 30, 2005
  3. -
    Replies:
    12
    Views:
    691
    Remon van Vliet
    Jun 15, 2005
  4. Byte
    Replies:
    4
    Views:
    414
  5. Isaac Won
    Replies:
    9
    Views:
    372
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page