format for declaring variables?

Discussion in 'C Programming' started by Daniel Rudy, Feb 9, 2007.

  1. Daniel Rudy

    Daniel Rudy Guest

    Hello Group,

    Consider the following code:


    /* form 1 */
    int main(void)
    {
    int i;
    char *p;

    /* do something */

    return(0);
    }



    /* form 2 */
    int main(void)
    int i;
    char *p;
    {

    /* do something */

    return(0);
    }

    It seems alot of unix code uses the second form for initializing
    variables. Alot of my code uses the first form. Is there any
    operational difference between the two?




    --
    Daniel Rudy

    Email address has been base64 encoded to reduce spam
    Decode email address using b64decode or uudecode -m

    Why geeks like computers: look chat date touch grep make unzip
    strip view finger mount fcsk more fcsk yes spray umount sleep
    Daniel Rudy, Feb 9, 2007
    #1
    1. Advertising

  2. Daniel Rudy

    Richard Bos Guest

    Daniel Rudy <> wrote:

    > /* form 1 */
    > int main(void)
    > {
    > int i;
    > char *p;


    > return(0);
    > }


    > /* form 2 */
    > int main(void)
    > int i;
    > char *p;
    > {


    > return(0);
    > }
    >
    > It seems alot of unix code uses the second form for initializing
    > variables.


    No, you don't, and if you did it isn't C.

    > Alot of my code uses the first form. Is there any
    > operational difference between the two?


    Yes. The former is C, the latter is not.

    What you _may_ have seen is this:

    int main()
    int i;
    char *p;
    {

    return(0);
    }

    Note the lack of a void keyword in the function header. This makes this
    an old-style declaration, rather than a prototype. They're obsolescent,
    and IMO should have been obsoleted in the 1999 C Standard. Very old code
    may still be around which was written like this in 18-something; code
    which still has to compile on antediluvial, pre-Standard compilers may
    still need to be written like this; but no normal code should be written
    like it today.

    Richard
    Richard Bos, Feb 9, 2007
    #2
    1. Advertising

  3. [code reflowed for vertical compression!]

    Daniel Rudy said:

    > Consider the following code:
    >
    > /* form 1 */
    > int main(void) { int i; char *p; /* do something */ return(0); }
    >
    > /* form 2 */
    > int main(void) int i; char *p; { /* do something */ return(0); }
    >
    > It seems alot of unix code uses the second form for initializing
    > variables. Alot of my code uses the first form. Is there any
    > operational difference between the two?


    The two forms are not equivalent, and indeed the second form is illegal.
    What I think you're trying to represent, which *is* legal, is:

    int main(i, p) int i; char **p; { return(0); }

    and it is basically an archaeological curiosity. It is equivalent to:

    int main(int i, char **p) { return(0); }

    except that this more up-to-date ("function prototype") version
    facilitates the compiler's type-checking - which is why it was
    introduced. The older form is still legal for hysterical reasons.

    Ignore the older version if you can. Better still, update code that uses
    it to adopt the prototype style.

    Incidentally, the parentheses around the 0 are redundant and pointless.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, Feb 9, 2007
    #3
  4. Daniel Rudy <> wrote:
    > /* form 1 */
    > int main(void)
    > {
    > int i;
    > char *p;


    > /* do something */


    > return(0);
    > }


    > /* form 2 */
    > int main(void)
    > int i;
    > char *p;
    > {


    > /* do something */


    > return(0);
    > }


    > It seems alot of unix code uses the second form for initializing
    > variables. Alot of my code uses the first form. Is there any
    > operational difference between the two?


    It's not about initializing variables but function parameters. And
    the second form is the correct form, the first form is from times
    before standardization of C by ANSI/ISO. i.e. from before 1989/90.
    It's only still supported for backward compatibility. And, actually,
    the way you write it isn't correct, if I remember correctly it would
    have to be

    int main(i,p)
    int i;
    char *p;

    making main() a function that takes an integer argument 'i' and a char
    pointer argument 'p' which would be written nowadays

    int main(int i, char *p)

    (Both are, of course, not standard-compliant since main() takes
    either no arguments or an int and a char** or an array of char*.)

    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, Feb 9, 2007
    #4
  5. Daniel Rudy

    Daniel Rudy Guest

    At about the time of 2/9/2007 1:25 AM, Daniel Rudy stated the following:
    > Hello Group,
    >


    snip

    >
    > It seems alot of unix code uses the second form for initializing
    > variables. Alot of my code uses the first form. Is there any
    > operational difference between the two?
    >


    I was using main as an example to demonstrate the form....and it should
    have been declaring and not initializing there too....

    Anyways, I know that this IS platform specific, but here's what I saw,
    copied verbatim from the source file:

    int
    kenv(td, uap)
    struct thread *td;
    struct kenv_args /* {
    int what;
    const char *name;
    char *value;
    int len;
    } */ *uap;
    {
    char *name, *value;
    size_t len, done, needed;
    int error, i;

    KASSERT(dynamic_kenv, ("kenv: dynamic_kenv = 0"));

    error = 0;
    if (uap->what == KENV_DUMP) {
    #ifdef MAC
    error = mac_check_kenv_dump(td->td_ucred);
    if (error)
    return (error);
    #endif
    done = needed = 0;
    sx_slock(&kenv_lock);
    for (i = 0; kenvp != NULL; i++) {


    I cut it short because it's pretty long. But if you want to see for
    yourself, FreeBSD 6.2-RELEASE /usr/src/sys/kern/kern_environment.c is
    where this code fragment came from. The CVS tag on the file is dated
    2005/10/09 which is pretty recent.


    --
    Daniel Rudy

    Email address has been base64 encoded to reduce spam
    Decode email address using b64decode or uudecode -m

    Why geeks like computers: look chat date touch grep make unzip
    strip view finger mount fcsk more fcsk yes spray umount sleep
    Daniel Rudy, Feb 9, 2007
    #5
  6. Daniel Rudy

    quarkLore Guest


    > except that this more up-to-date ("function prototype") version
    > facilitates the compiler's type-checking - which is why it was
    > introduced. The older form is still legal for hysterical reasons.
    >
    > Ignore the older version if you can. Better still, update code that uses
    > it to adopt the prototype style.
    >


    Following compiles with gcc (version 3.2.2). Even if I use strict
    flags like -ansi -Wall -Werror without warning or error. So using this
    you can potentially landup in a mess.

    int myf(i)
    int i;
    {
    /* do something */
    return(0);
    }

    int main(void)
    {
    myf(10,10);
    return 0;
    }
    quarkLore, Feb 9, 2007
    #6
  7. Daniel Rudy

    Daniel Rudy Guest

    At about the time of 2/9/2007 1:43 AM, Jens Thoms Toerring stated the
    following:
    > Daniel Rudy <> wrote:
    >> /* form 1 */
    >> int main(void)
    >> {
    >> int i;
    >> char *p;

    >
    >> /* do something */

    >
    >> return(0);
    >> }

    >
    >> /* form 2 */
    >> int main(void)
    >> int i;
    >> char *p;
    >> {

    >
    >> /* do something */

    >
    >> return(0);
    >> }

    >
    >> It seems alot of unix code uses the second form for initializing
    >> variables. Alot of my code uses the first form. Is there any
    >> operational difference between the two?

    >
    > It's not about initializing variables but function parameters. And
    > the second form is the correct form, the first form is from times
    > before standardization of C by ANSI/ISO. i.e. from before 1989/90.
    > It's only still supported for backward compatibility.


    > And, actually,
    > the way you write it isn't correct, if I remember correctly it would
    > have to be
    >


    That's interesting, because on programs that don't take arguments, I
    always do int main(void).

    > int main(i,p)
    > int i;
    > char *p;
    >


    Hmm...maybe I missed something.


    > making main() a function that takes an integer argument 'i' and a char
    > pointer argument 'p' which would be written nowadays
    >
    > int main(int i, char *p)
    >
    > (Both are, of course, not standard-compliant since main() takes
    > either no arguments or an int and a char** or an array of char*.)
    >
    > Regards, Jens
    > --
    > \ Jens Thoms Toerring ___
    > \__________________________ http://toerring.de



    --
    Daniel Rudy

    Email address has been base64 encoded to reduce spam
    Decode email address using b64decode or uudecode -m

    Why geeks like computers: look chat date touch grep make unzip
    strip view finger mount fcsk more fcsk yes spray umount sleep
    Daniel Rudy, Feb 9, 2007
    #7
  8. Daniel Rudy said:

    <snip>

    > Anyways, I know that this IS platform specific,


    Fortunately, that doesn't matter here (and anyway, you tried, right?).

    > but here's what I saw, copied verbatim from the source file:
    >
    > int
    > kenv(td, uap)
    > struct thread *td;
    > struct kenv_args /* [...] */ *uap;
    > {


    That's legal.

    The modern form is:
    int
    kenv(struct thread *td, struct kenv_args *uap)
    {

    They have identical semantics for all intents and purposes, except that
    the latter form allows stricter type-checking by the compiler.

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

    >> Ignore the older version if you can. Better still, update code that
    >> uses it to adopt the prototype style.
    >>

    >
    > Following compiles with gcc (version 3.2.2). Even if I use strict
    > flags like -ansi -Wall -Werror without warning or error. So using this
    > you can potentially landup in a mess.
    >
    > int myf(i)
    > int i;
    > {
    > /* do something */
    > return(0);
    > }
    >
    > int main(void)
    > {
    > myf(10,10);
    > return 0;
    > }


    Which is precisely why I suggested updating the code to use the
    prototype style.
    </confused>

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

    Chris Dollin Guest

    Daniel Rudy wrote:

    > OT: Speaking of style, forms like this bug me:
    >
    > if ((fc = open(filename)) < 0)
    > errx("file error %d\n", errno);
    >
    > How hard is it to sit there and do this instead?
    >
    > fc = open(filename);
    > if (fc < 0) errx("file error %d\n", errno);
    >
    > It's just so much easier to read, less error prone (since there are
    > fewer nested () ), and it probably generates the exact same code at the
    > machine level.


    But doesn't work as part of an else-if without putting up
    extra scaffolding.

    (Myself, I want to know why I can't put /declarations/ in
    the conditions of an if [1,2].)

    [1] Because then I don't have to introduce variables before
    I know their values.

    [2] Yes, it can be done cleanly, although I haven't thought
    hard about it /for C/.

    --
    Chris "electric hedgehog" Dollin
    "Our future looks secure, but it's all out of our hands"
    - Magenta, /Man and Machine/
    Chris Dollin, Feb 9, 2007
    #10
  11. Daniel Rudy

    Daniel Rudy Guest

    At about the time of 2/9/2007 2:03 AM, Richard Heathfield stated the
    following:
    > Daniel Rudy said:
    >
    > <snip>
    >
    >> Anyways, I know that this IS platform specific,

    >
    > Fortunately, that doesn't matter here (and anyway, you tried, right?).
    >


    Tried? Not sure what you mean there...

    >> but here's what I saw, copied verbatim from the source file:
    >>
    >> int
    >> kenv(td, uap)
    >> struct thread *td;
    >> struct kenv_args /* [...] */ *uap;
    >> {

    >
    > That's legal.


    Ok. That form threw me for a loop. I had no idea what was going on.

    > The modern form is:
    > int
    > kenv(struct thread *td, struct kenv_args *uap)
    > {
    >
    > They have identical semantics for all intents and purposes, except that
    > the latter form allows stricter type-checking by the compiler.
    >


    I've only used the modern form. People using different styles like that
    makes the code much harder to read and decipher. But for a project as
    complicated as an operating system kernel (that's what that code
    fragment is from), you have a bunch of different people working on
    different parts and everybody has their own style.


    OT: Speaking of style, forms like this bug me:

    if ((fc = open(filename)) < 0)
    errx("file error %d\n", errno);

    How hard is it to sit there and do this instead?

    fc = open(filename);
    if (fc < 0) errx("file error %d\n", errno);

    It's just so much easier to read, less error prone (since there are
    fewer nested () ), and it probably generates the exact same code at the
    machine level.


    --
    Daniel Rudy

    Email address has been base64 encoded to reduce spam
    Decode email address using b64decode or uudecode -m

    Why geeks like computers: look chat date touch grep make unzip
    strip view finger mount fcsk more fcsk yes spray umount sleep
    Daniel Rudy, Feb 9, 2007
    #11
  12. Daniel Rudy said:

    > At about the time of 2/9/2007 2:03 AM, Richard Heathfield stated the
    > following:
    >> Daniel Rudy said:
    >>
    >> <snip>
    >>
    >>> Anyways, I know that this IS platform specific,

    >>
    >> Fortunately, that doesn't matter here (and anyway, you tried,
    >> right?).
    >>

    >
    > Tried? Not sure what you mean there...


    I mean that you made an effort in your original article to present the
    problem in a platform-independent way - which was good. Okay, it didn't
    work out on this occasion, and it turns out it didn't matter anyway,
    but you did make the effort.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, Feb 9, 2007
    #12
  13. Daniel Rudy <> writes:
    > At about the time of 2/9/2007 1:43 AM, Jens Thoms Toerring stated the
    > following:

    [...]
    >> And, actually,
    >> the way you write it isn't correct, if I remember correctly it would
    >> have to be
    >>


    Um, you snipped what Jens said it would have to be. Oh, well.

    > That's interesting, because on programs that don't take arguments, I
    > always do int main(void).


    Yes, that's valid.

    There are two permitted forms for main:

    int main(int argc, char *argv[]) { /* ... */ }

    int main(void) { /* ... */ }

    (or equivalent).

    This:

    int main(argc, argv)
    int argc;
    char *argv;
    {
    /* ... */
    }

    is an old-style declaration; it's still legal, but it shouldn't be
    used in new code.

    >> int main(i,p)
    >> int i;
    >> char *p;
    >>


    That's equivalent to the above old-style declarations (the parameters
    don't have to be named "argc" and "argv", but they are by convention,
    and there's no good reason to use different names) -- except that
    "char *p;" should be "char **p;" or "char *p[];".

    [...]

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Feb 9, 2007
    #13
  14. Daniel Rudy

    CBFalconer Guest

    Daniel Rudy wrote:
    >

    .... snip ...
    >
    > OT: Speaking of style, forms like this bug me:
    >
    > if ((fc = open(filename)) < 0)
    > errx("file error %d\n", errno);
    >
    > How hard is it to sit there and do this instead?
    >
    > fc = open(filename);
    > if (fc < 0) errx("file error %d\n", errno);
    >
    > It's just so much easier to read, less error prone (since there
    > are fewer nested () ), and it probably generates the exact same
    > code at the machine level.


    While I am annoyed by (not to mention the non-existent open):

    fc = fopen(filename, etc);
    if (!fc) erroraction();
    dowhatever(fc);

    when

    if (!(fc = fopen(filename, etc)))
    erroraction(filename);
    else (
    /* all is well */
    dowhatever(fc);
    }

    will show me precisely what is required to get to dowhatever, or to
    erroraction. I also know that I will not fall into dowhatever when
    erroraction (somewhere else) returns. I also trivially know that
    dowhatever has a valid opened fc value passed to it.

    Note that the preferred method above can be wrapped in:

    do {
    filename = getfcspecification();
    if (!(fc = fopen(filename, etc)))
    erroraction(filename);
    else (
    /* all is well */
    dowhatever(fc);
    }
    } while (!fc);
    fclose(fc); /* knowing that fc is non-NULL */

    It is clearer because the thing that is being tested is the success
    of fopen, not the value of fc (which is incidental). It also leads
    to single entry / single exit modules, and conserves vertical
    space, all of which enhances code readability.

    Think it over.

    --
    <http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
    <http://www.securityfocus.com/columnists/423>

    "A man who is right every time is not likely to do very much."
    -- Francis Crick, co-discover of DNA
    "There is nothing more amazing than stupidity in action."
    -- Thomas Matthews
    CBFalconer, Feb 9, 2007
    #14
  15. Daniel Rudy

    Daniel Rudy Guest

    At about the time of 2/9/2007 3:09 AM, Keith Thompson stated the following:
    > Daniel Rudy <> writes:
    >> At about the time of 2/9/2007 1:43 AM, Jens Thoms Toerring stated the
    >> following:

    > [...]
    >>> And, actually,
    >>> the way you write it isn't correct, if I remember correctly it would
    >>> have to be
    >>>

    >
    > Um, you snipped what Jens said it would have to be. Oh, well.
    >


    It was snipped because my example was in error. That's what I get for
    copying something from memory. :)

    >> That's interesting, because on programs that don't take arguments, I
    >> always do int main(void).

    >
    > Yes, that's valid.
    >
    > There are two permitted forms for main:
    >
    > int main(int argc, char *argv[]) { /* ... */ }
    >
    > int main(void) { /* ... */ }
    >
    > (or equivalent).
    >
    > This:
    >
    > int main(argc, argv)
    > int argc;
    > char *argv;
    > {
    > /* ... */
    > }
    >
    > is an old-style declaration; it's still legal, but it shouldn't be
    > used in new code.
    >


    Which begs the question as to why they did it that way.

    >>> int main(i,p)
    >>> int i;
    >>> char *p;
    >>>

    >
    > That's equivalent to the above old-style declarations (the parameters
    > don't have to be named "argc" and "argv", but they are by convention,
    > and there's no good reason to use different names) -- except that
    > "char *p;" should be "char **p;" or "char *p[];".
    >
    > [...]
    >


    I've never used anything but this for programs that take command line
    arguments:

    int main(int argc, char **argv)

    But you say that you can also do this?

    int main(int argc, char *argv[])

    Hmmm.... It seems that second form might be better suited for argument
    processing then that first one. I've always had problems properly
    interpreting what ** meant, although I know it's a pointer to a pointer.



    --
    Daniel Rudy

    Email address has been base64 encoded to reduce spam
    Decode email address using b64decode or uudecode -m

    Why geeks like computers: look chat date touch grep make unzip
    strip view finger mount fcsk more fcsk yes spray umount sleep
    Daniel Rudy, Feb 13, 2007
    #15
  16. Daniel Rudy

    Daniel Rudy Guest

    Style (Was: Re: format for declaring variables?)

    At about the time of 2/9/2007 2:20 AM, Chris Dollin stated the following:
    > Daniel Rudy wrote:
    >
    >> OT: Speaking of style, forms like this bug me:
    >>
    >> if ((fc = open(filename)) < 0)
    >> errx("file error %d\n", errno);
    >>
    >> How hard is it to sit there and do this instead?
    >>
    >> fc = open(filename);
    >> if (fc < 0) errx("file error %d\n", errno);
    >>
    >> It's just so much easier to read, less error prone (since there are
    >> fewer nested () ), and it probably generates the exact same code at the
    >> machine level.

    >
    > But doesn't work as part of an else-if without putting up
    > extra scaffolding.
    >
    > (Myself, I want to know why I can't put /declarations/ in
    > the conditions of an if [1,2].)
    >
    > [1] Because then I don't have to introduce variables before
    > I know their values.
    >
    > [2] Yes, it can be done cleanly, although I haven't thought
    > hard about it /for C/.
    >


    I've seen code like this that compiles just fine under C with all
    warnings enabled (or at least the ones that I have turned on):

    int function(int i)
    {
    switch(i)
    {
    case 0:
    {
    int a;
    /* do something */
    return(0);
    }
    case 1:
    {
    char *p;
    /* do something */
    return(0);
    }
    case 2:
    {
    unsigned long lax;
    /* do something */
    return(0);
    }
    default:
    return(1);
    }
    return(0);
    }

    And here's the actual code:

    char * inet_ntop_host(const struct sockaddr *sa, socklen_t salen)
    {
    char portstr[8];
    static char str[128];

    switch(sa->sa_family)
    {
    case AF_INET:
    {
    struct sockaddr_in *sin = (struct sockaddr_in *) sa;
    if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) ==
    NULL) return(NULL);
    if(ntohs(sin->sin_port) != 0)
    {
    snprintf(portstr, sizeof(portstr), ":%d",
    ntohs(sin->sin_port));
    strcat(str, portstr);
    }
    return(str);
    }
    #ifdef IPV6
    case AF_INET6:
    {
    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
    if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str))
    == NULL) return(NULL);
    if(ntohs(sin6->sin6_port) != 0)
    {
    snprintf(portstr, sizeof(portstr), ":%d",
    ntohs(sini6->sin6_port));
    strcat(str, portstr);
    }
    return(str);
    }
    #endif
    #ifdef AF_UNIX
    case AF_UNIX:
    {
    struct sockaddr_un *unp = (struct sockaddr_un *) sa;
    if (unp->sun_path[0] == 0) strcpy(str, "(no pathname bound)");
    else snprintf(str, sizeof(str), "%s", unp->sun_path);
    return(str);
    }
    #endif
    default:
    snprintf(str, sizeof(str), "sock_ntop_host: unknown AF_xxx:
    %d, len %d", sa->sa_family, salen);
    return(NULL);
    break;
    }
    return(NULL);
    }

    --
    Daniel Rudy

    Email address has been base64 encoded to reduce spam
    Decode email address using b64decode or uudecode -m

    Why geeks like computers: look chat date touch grep make unzip
    strip view finger mount fcsk more fcsk yes spray umount sleep
    Daniel Rudy, Feb 13, 2007
    #16
  17. Daniel Rudy

    Daniel Rudy Guest

    At about the time of 2/9/2007 2:32 AM, Richard Heathfield stated the
    following:
    > Daniel Rudy said:
    >
    >> At about the time of 2/9/2007 2:03 AM, Richard Heathfield stated the
    >> following:
    >>> Daniel Rudy said:
    >>>
    >>> <snip>
    >>>
    >>>> Anyways, I know that this IS platform specific,
    >>> Fortunately, that doesn't matter here (and anyway, you tried,
    >>> right?).
    >>>

    >> Tried? Not sure what you mean there...

    >
    > I mean that you made an effort in your original article to present the
    > problem in a platform-independent way - which was good. Okay, it didn't
    > work out on this occasion, and it turns out it didn't matter anyway,
    > but you did make the effort.
    >


    Oh, ok.

    So I get a B for effort then? I guess I would have gotten an A if my
    example was correct.

    --
    Daniel Rudy

    Email address has been base64 encoded to reduce spam
    Decode email address using b64decode or uudecode -m

    Why geeks like computers: look chat date touch grep make unzip
    strip view finger mount fcsk more fcsk yes spray umount sleep
    Daniel Rudy, Feb 13, 2007
    #17
  18. Daniel Rudy

    Daniel Rudy Guest

    At about the time of 2/9/2007 7:22 AM, CBFalconer stated the following:
    > Daniel Rudy wrote:
    > ... snip ...
    >> OT: Speaking of style, forms like this bug me:
    >>
    >> if ((fc = open(filename)) < 0)
    >> errx("file error %d\n", errno);
    >>
    >> How hard is it to sit there and do this instead?
    >>
    >> fc = open(filename);
    >> if (fc < 0) errx("file error %d\n", errno);
    >>
    >> It's just so much easier to read, less error prone (since there
    >> are fewer nested () ), and it probably generates the exact same
    >> code at the machine level.

    >
    > While I am annoyed by (not to mention the non-existent open):


    Hmm...open(2) exists on my system, but then again, I'm running Unix, so
    it's probably not in the standard C library. It does the same thing as
    fopen though, but take different parameters.

    >
    > fc = fopen(filename, etc);
    > if (!fc) erroraction();
    > dowhatever(fc);
    >
    > when
    >
    > if (!(fc = fopen(filename, etc)))
    > erroraction(filename);
    > else (
    > /* all is well */
    > dowhatever(fc);
    > }


    I would write that like this:

    fc = fopen(filename, etc);
    if (fc == NULL)
    {
    ERR("fopen failed", errno, 1)
    return(EFUNCTERR);
    }
    dowhatever(fc);
    return(0);

    ERR is a macro that I made that is defined like this:

    #define ERR(MM,CC,EE) ERROR(MM, PARAM_XXX_ERROR_SHOW,
    PARAM_XXX_ERROR_FATAL, CC, EE)

    From there, there is a #define ERROR and then it goes on to my error
    handler.


    > will show me precisely what is required to get to dowhatever, or to
    > erroraction. I also know that I will not fall into dowhatever when
    > erroraction (somewhere else) returns. I also trivially know that
    > dowhatever has a valid opened fc value passed to it.
    >
    > Note that the preferred method above can be wrapped in:
    >
    > do {
    > filename = getfcspecification();
    > if (!(fc = fopen(filename, etc)))
    > erroraction(filename);
    > else (
    > /* all is well */
    > dowhatever(fc);
    > }
    > } while (!fc);
    > fclose(fc); /* knowing that fc is non-NULL */
    >
    > It is clearer because the thing that is being tested is the success
    > of fopen, not the value of fc (which is incidental). It also leads
    > to single entry / single exit modules, and conserves vertical
    > space, all of which enhances code readability.
    >
    > Think it over.
    >


    The problem that I have with that is the if line.

    if (!(fc = fopen(filename, etc)))

    I'm not savvy doing tricks like that, so I would have to think about
    that statement to fully grasp the meaning of it. For the most part, I
    follow the single entry / exit, but in the case of errors, I do an
    immediate return with an error indication.

    --
    Daniel Rudy

    Email address has been base64 encoded to reduce spam
    Decode email address using b64decode or uudecode -m

    Why geeks like computers: look chat date touch grep make unzip
    strip view finger mount fcsk more fcsk yes spray umount sleep
    Daniel Rudy, Feb 13, 2007
    #18
  19. Daniel Rudy <> writes:
    > At about the time of 2/9/2007 3:09 AM, Keith Thompson stated the following:

    [...]
    >> There are two permitted forms for main:
    >>
    >> int main(int argc, char *argv[]) { /* ... */ }
    >>
    >> int main(void) { /* ... */ }
    >>
    >> (or equivalent).
    >>
    >> This:
    >>
    >> int main(argc, argv)
    >> int argc;
    >> char *argv;
    >> {
    >> /* ... */
    >> }
    >>
    >> is an old-style declaration; it's still legal, but it shouldn't be
    >> used in new code.
    >>

    >
    > Which begs the question as to why they did it that way.


    I think it goes back to C's ancestor languages B and BCPL, and
    possibly to Fortran. In the old days, the idea was that the compiler
    would generate code for a call to a function based on the arguments in
    the call; they weren't cross-checked against what the function
    expected. The declarations of the types of the parameters are
    internal to the function, and not visible at the point of call. If
    you correctly pass an int and a char**, that's great. If you pass a
    double and a function pointer, you lose, and the compiler won't help
    you by printing an error message.

    Prototypes, which specify the number and types of the expected
    arguments, were a considerable improvement.

    [...]

    > I've never used anything but this for programs that take command line
    > arguments:
    >
    > int main(int argc, char **argv)
    >
    > But you say that you can also do this?
    >
    > int main(int argc, char *argv[])


    In a parameter declaration (and *only* in a parameter declaration),
    "char **argv" and "char *argv[]" are exactly equivalent.

    The relationship between arrays and pointers in C is a tremendous
    source of confusion. It's not really all that complex once you learn
    the rules. But this special-case rule that what looks like an array
    parameter declaration is really a pointer parameter declaration just
    adds to the confusion, in my opinion. I recommend sections 4 and 6 of
    the comp.lang.c FAQ, <http://www.c-faq.com/>.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Feb 14, 2007
    #19
  20. Re: Style (Was: Re: format for declaring variables?)

    Daniel Rudy wrote:

    >> Daniel Rudy wrote:
    >>
    >>> OT: Speaking of style, forms like this bug me:
    >>>
    >>> if ((fc = open(filename)) < 0)
    >>> errx("file error %d\n", errno);
    >>>
    >>> How hard is it to sit there and do this instead?


    Hard. Get used to the idiom, it's not a big deal unless it's causing line
    wrapping issues. The idiom will become familiar to you in use.

    >>> fc = open(filename);
    >>> if (fc < 0) errx("file error %d\n", errno);
    >>>
    >>> It's just so much easier to read, less error prone (since there are
    >>> fewer nested () ), and it probably generates the exact same code at the
    >>> machine level.


    Vertical real estate is always in demand unless you've got a different type of
    monitor/terminal.

    > I've seen code like this that compiles just fine under C with all
    > warnings enabled (or at least the ones that I have turned on):


    But you forgot the -Wimpending-beating option for indentation like that. That
    is ridiculous.

    Regardless of your level of affinity towards Linux (which might well be none
    since I saw you mention FBSD), this is a good guide with clean semantics and
    pragmatic execution:

    Linux Kernel Coding Style guide:
    http://www.mjmwired.net/kernel/Documentation/CodingStyle

    With such classic Linus gems such as:

    16 Chapter 1: Indentation
    17
    18 Tabs are 8 characters, and thus indentations are also 8 characters.
    19 There are heretic movements that try to make indentations 4 (or even 2!)
    20 characters deep, and that is akin to trying to define the value of PI to
    21 be 3.
    22
    23 Rationale: The whole idea behind indentation is to clearly define where
    24 a block of control starts and ends. Especially when you've been looking
    25 at your screen for 20 straight hours, you'll find it a lot easier to see
    26 how the indentation works if you have large indentations.
    27
    28 Now, some people will claim that having 8-character indentations makes
    29 the code move too far to the right, and makes it hard to read on a
    30 80-character terminal screen. The answer to that is that if you need
    31 more than 3 levels of indentation, you're screwed anyway, and should fix
    32 your program.

    and

    97 Chapter 3: Placing Braces and Spaces
    98
    99 The other issue that always comes up in C styling is the placement of
    100 braces. Unlike the indent size, there are few technical reasons to
    101 choose one placement strategy over the other, but the preferred way, as
    102 shown to us by the prophets Kernighan and Ritchie, is to put the opening
    103 brace last on the line, and put the closing brace first, thusly:
    104
    105 if (x is true) {
    106 we do y
    107 }
    [...]
    108
    123 However, there is one special case, namely functions: they have the
    124 opening brace at the beginning of the next line, thus:
    125
    126 int function(int x)
    127 {
    128 body of function
    129 }
    130
    131 Heretic people all over the world have claimed that this inconsistency
    132 is ... well ... inconsistent, but all right-thinking people know that
    133 (a) K&R are _right_ and (b) K&R are right. Besides, functions are
    134 special anyway (you can't nest them in C).

    Amen.
    Christopher Layne, Feb 14, 2007
    #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. Mortal Wombat
    Replies:
    3
    Views:
    6,829
    Mortal Wombat
    Aug 7, 2003
  2. Rob Meade

    Declaring variables - best practice?

    Rob Meade, Nov 24, 2003, in forum: ASP .Net
    Replies:
    2
    Views:
    464
    Rob Meade
    Nov 24, 2003
  3. Steven K

    Newbie: Declaring Variables

    Steven K, Feb 27, 2004, in forum: ASP .Net
    Replies:
    5
    Views:
    426
    Alvin Bruney [MVP]
    Feb 28, 2004
  4. =?Utf-8?B?QXNoYQ==?=

    help in declaring variables

    =?Utf-8?B?QXNoYQ==?=, Dec 31, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    327
    John Saunders
    Dec 31, 2004
  5. Joey P
    Replies:
    0
    Views:
    556
    Joey P
    Oct 10, 2004
Loading...

Share This Page