Please help optimize (and standarize) this code...

Discussion in 'C Programming' started by gtippery, Feb 21, 2005.

  1. gtippery

    gtippery Guest

    Newbie-ish questions - I've been away from C for a _long_ time.

    It seems to me that there ought to be easier (or at least shorter) ways
    to do what this does. It does compile & run for me (with PowerC, a
    16-bit DOS compiler); if there are nonstandard or "accidentally-works"
    aspects, please let me know.

    {This is the sort of situation where if I knew *what* to Google for, I
    wouldn't *need* to... <grin>}

    Code follows:

    ---------------------- snip ------------------------
    #include <stdio.h>
    #include <stdlib.h> /* for itoa */
    #include <string.h> /* for memcpy(), strcpy(), strcat() */

    #define NAMLEN 8
    #define EXTLEN 3
    #define MAX 512
    #define MAXCOL 1

    typedef struct {
    char name[NAMLEN];
    char ext[EXTLEN];
    } NameExt;

    NameExt NameArray[MAX+1];
    int NameCnt=0;

    main()
    {
    //...
    char fmtstr[32], digits[12];
    int i;
    char NAM[NAMLEN+1], EXT[EXTLEN+1];
    int colnum = 0;

    //...
    /* Fill the array with (test) names & extensions,
    left-justified & space-filled (no (char)0's).
    In the real app (...'d code), there's findfirst(),
    findnext(), sorting, etc.*/

    memcpy(&NameArray[0], "One 1 ", 11);
    memcpy(&NameArray[1], "TwoTwoTw222", 11);
    memcpy(&NameArray[2], "333 003", 11);
    NameCnt = 3;
    //...

    /* Print names & extensions in multiple columns */

    // Construct format string like "%8s%c%3s"
    strcpy(fmtstr, "%");
    strcat(fmtstr, itoa(NAMLEN, digits, 10));
    strcat(fmtstr, "s%c%");
    strcat(fmtstr, itoa(EXTLEN, digits, 10));
    strcat(fmtstr, "s");

    // Print according to the specified format
    for(i=0; i<NameCnt; i++) {
    memcpy(NAM, NameArray.name, NAMLEN);
    NAM[NAMLEN] = (char)0;
    memcpy(EXT, NameArray.ext, EXTLEN);
    EXT[EXTLEN] = (char)0;
    printf(fmtstr, NAM, '.', EXT);

    // Handle columnizing here
    if(colnum++ < MAXCOL) {
    printf(" ");
    } else {
    printf("\n");
    colnum = 0;
    }
    }
    printf("\n");
    //...
    }
    ---------------------- snip ------------------------

    Particularly, are there easier ways to:
    (1) initialize the NameArray records;
    (2) specify the format string, assuming I want to stick with constants
    for the field widths; and
    (3) printf the NameArray array-of-char fields without explicitly
    converting them to strings?

    Also, is there a way to get e.g.,
    sizeof NameExt.Ext
    (which doesn't work) at compile-time?

    TIA!
    gtippery, Feb 21, 2005
    #1
    1. Advertising

  2. gtippery

    -berlin.de Guest

    gtippery <> wrote:
    > Newbie-ish questions - I've been away from C for a _long_ time.


    > It seems to me that there ought to be easier (or at least shorter) ways
    > to do what this does. It does compile & run for me (with PowerC, a
    > 16-bit DOS compiler); if there are nonstandard or "accidentally-works"
    > aspects, please let me know.


    > {This is the sort of situation where if I knew *what* to Google for, I
    > wouldn't *need* to... <grin>}


    > Code follows:


    > ---------------------- snip ------------------------
    > #include <stdio.h>
    > #include <stdlib.h> /* for itoa */


    Sorry, but itoa() is an extension that you won't always find in
    <stdlib.h>.

    > #include <string.h> /* for memcpy(), strcpy(), strcat() */


    > #define NAMLEN 8
    > #define EXTLEN 3
    > #define MAX 512
    > #define MAXCOL 1


    > typedef struct {
    > char name[NAMLEN];
    > char ext[EXTLEN];
    > } NameExt;


    > NameExt NameArray[MAX+1];
    > int NameCnt=0;


    > main()


    If you want to be sure that this also works with a C99 compiler you
    must at least tell the compiler the return type of main() (which
    must be int), since the old default assumption, that a function
    without a declared return type will return int does not hold anymore.
    Also telling the compiler the number of arguments is reasonable, so
    you better make that either

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

    > {
    > //...
    > char fmtstr[32], digits[12];
    > int i;
    > char NAM[NAMLEN+1], EXT[EXTLEN+1];
    > int colnum = 0;


    > //...
    > /* Fill the array with (test) names & extensions,
    > left-justified & space-filled (no (char)0's).
    > In the real app (...'d code), there's findfirst(),
    > findnext(), sorting, etc.*/


    > memcpy(&NameArray[0], "One 1 ", 11);


    This obviously assumes that the members of the NameExt structure are
    packed, i.e. that the 'ext' member starts immediately after the 'name'
    member without any padding in between. While you probably often will
    get away with that it's not guaranteed to work since the compiler is
    free to insert as many padding bytes between (and after) the members
    as it likes. And if it does your scheme won't work anymore. So you
    better make that

    memcpy( &NameArray[0].name, "One ", NAMLEN );
    memcpy( &NameArray[0].ext, "1 ", EXTLEN );

    > memcpy(&NameArray[1], "TwoTwoTw222", 11);
    > memcpy(&NameArray[2], "333 003", 11);
    > NameCnt = 3;
    > //...


    > /* Print names & extensions in multiple columns */


    > // Construct format string like "%8s%c%3s"
    > strcpy(fmtstr, "%");
    > strcat(fmtstr, itoa(NAMLEN, digits, 10));


    itoa() isn't a standard C function, so this will fail on systems
    where there's no ito().

    > strcat(fmtstr, "s%c%");
    > strcat(fmtstr, itoa(EXTLEN, digits, 10));
    > strcat(fmtstr, "s");


    Why don't you use sprintf() to make up the format string?

    sprintf( fmtstr, "%%%ds%%c%%%ds" NAMLEN, EXTLEN );

    > // Print according to the specified format
    > for(i=0; i<NameCnt; i++) {
    > memcpy(NAM, NameArray.name, NAMLEN);
    > NAM[NAMLEN] = (char)0;


    "(char)0" is probably better written as "'\0'", at least then all
    C programmers with a bit of experience will know what you mean.

    > memcpy(EXT, NameArray.ext, EXTLEN);
    > EXT[EXTLEN] = (char)0;
    > printf(fmtstr, NAM, '.', EXT);


    > // Handle columnizing here
    > if(colnum++ < MAXCOL) {
    > printf(" ");
    > } else {
    > printf("\n");
    > colnum = 0;
    > }
    > }
    > printf("\n");
    > //...
    > }
    > ---------------------- snip ------------------------


    > Particularly, are there easier ways to:
    > (1) initialize the NameArray records;


    Perhaps, but that will depend on what you want to initialize the array
    elements with in the real case. Since I don't know what findfirst() and
    findnext() return (they aren't standard C functions) it's impossible to
    say if there's a simpler way to assign values to the structure members.

    > (2) specify the format string, assuming I want to stick with constants
    > for the field widths; and
    > (3) printf the NameArray array-of-char fields without explicitly
    > converting them to strings?


    You actually don't have to do that since you specify the length of them,
    so even without the terminating '\0' characters it will work correctly.
    You can safely do

    printf( fmtstr, NameArry[ 0 ].name, '.', NameArray[ 0 ].ext );

    when 'fmtstr' is e.g. "%8s%c%3s".

    BTW, an alternative would be to use

    printf( "%*s%c%*s", NAMLEN, NameArray[ 0 ].name, '.',
    EXTLEN, NameArray[ 0 ].ext );
    or
    printf( "%*s%c%*s", sizeof NameArray->name, NameArray[ 0 ].name, '.',
    sizeof NameArray->ext, NameArray[ 0 ].ext );

    > Also, is there a way to get e.g.,
    > sizeof NameExt.Ext
    > (which doesn't work) at compile-time?


    Yes, if you give sizeof the name of a real instance of the NameExt
    struct, i.e.

    sizeof NameArray[ 0 ].ext
    or
    sizeof NameArray->ext
    Regards, Jens
    --
    \ Jens Thoms Toerring ___ -berlin.de
    \__________________________ http://www.toerring.de
    -berlin.de, Feb 21, 2005
    #2
    1. Advertising

  3. gtippery

    gtippery Guest

    Thanks for replying.


    >> #include <stdlib.h> /* for itoa */

    >
    > Sorry, but itoa() is an extension that you won't always find in
    > <stdlib.h>.


    Yeah, I had to dig a bit to even find it, in my compiler's library -
    I guess it was "depreciated" even in 1993...


    >> main()

    >

    ....
    > you better make that either
    >
    > int main( void )
    > or
    > int main( int argc, char *argv[ ] )
    >


    Yup. I did that deliberately to provoke someone to answer.
    <grin> That's gotta be either #1 or #2 on the 'most frequent"
    list...


    >> /* Fill the array with (test) names & extensions,
    >> left-justified & space-filled (no (char)0's).
    >> In the real app (...'d code), there's findfirst(),
    >> findnext(), sorting, etc.*/
    >> memcpy(&NameArray[0], "One 1 ", 11);

    >
    >
    > This obviously assumes that the members of the NameExt structure are
    > packed, i.e. that the 'ext' member starts immediately after the

    'name'
    > member without any padding in between. While you probably often will
    > get away with that it's not guaranteed to work since the compiler is
    > free to insert as many padding bytes between (and after) the members
    > as it likes. And if it does your scheme won't work anymore. So you
    > better make that
    >
    > memcpy( &NameArray[0].name, "One ", NAMLEN );
    > memcpy( &NameArray[0].ext, "1 ", EXTLEN );
    >


    A good point, and exactly the sort of thing I wanted to know.


    >> // Construct format string like "%8s%c%3s"
    >> strcpy(fmtstr, "%");
    >> strcat(fmtstr, itoa(NAMLEN, digits, 10));


    > itoa() isn't a standard C function, so this will fail on systems
    > where there's no itoa().


    Do you suggest sprintf(), or is there a standard, specific
    integer-to-characters function? BTW, do you know if itoa()
    [or something equivalent] is not standardized because character
    sets aren't, or is there some other reason?


    >> strcat(fmtstr, "s%c%");
    >> strcat(fmtstr, itoa(EXTLEN, digits, 10));
    >> strcat(fmtstr, "s");

    >
    >
    > Why don't you use sprintf() to make up the format string?
    >
    > sprintf( fmtstr, "%%%ds%%c%%%ds" NAMLEN, EXTLEN );
    >


    Argh! Because it didn't occur to me. I _did_ consider using
    sprintf() to format the entire output line, but not just the
    format string.


    >
    >> // Print according to the specified format
    >> for(i=0; i<NameCnt; i++) {
    >> memcpy(NAM, NameArray.name, NAMLEN);
    >> NAM[NAMLEN] = (char)0;

    >
    >
    > "(char)0" is probably better written as "'\0'", at least then all
    > C programmers with a bit of experience will know what you mean.
    >


    I _knew_ there was a simpler way than (char)0, but while my
    compiler accepts charvar = 0x00 and charvar = \0, neither looked
    "explicit" enought. I guess I'd forgotten you could use escaped
    characters in '' constants like you can in "" constants.


    >> Particularly, are there easier ways to:
    >> (1) initialize the NameArray records;


    [Your corrected version requoted here for reference:]

    > memcpy( &NameArray[0].name, "One ", NAMLEN );
    > memcpy( &NameArray[0].ext, "1 ", EXTLEN );



    >
    > Perhaps, but that will depend on what you want to initialize the

    array
    > elements with in the real case.


    Well, for illustration purposes, is there a better way to do
    what it _does_ do (setting an array-of-char field of a
    structure to a text constant) than using memcpy()?


    > Since I don't know what findfirst() and
    > findnext() return (they aren't standard C functions)


    They're MS-DOS functions; in my library they return a pointer to
    a structure full of binary values for file size, dates, etc.

    What's the standard-C way to get the contents of a directory? I
    have a few C reference books, but they date from the 1980's.
    (And I wasn't around them when I originally posted.)

    >
    >> (2) specify the format string, assuming I want to stick with

    constants
    >> for the field widths; and
    >> (3) printf the NameArray array-of-char fields without explicitly
    >> converting them to strings?

    >
    >
    > You actually don't have to do that since you specify the length of

    them,
    > so even without the terminating '\0' characters it will work

    correctly.
    > You can safely do
    >
    > printf( fmtstr, NameArry[ 0 ].name, '.', NameArray[ 0 ].ext );
    >
    > when 'fmtstr' is e.g. "%8s%c%3s".


    I attempted something like that - I originally wrote "%8c%c%3c",
    but then realized that wouldn't do what I wanted, and

    printf("%c%c%c%c%c%c%c%c%c%c%c%c",
    NameArray.name[0],
    NameArray.name[1],
    ...
    NameArray.ext[2]);
    was just "over the top". <grin> C doesn't have anything like
    FORTRAN's "implicit DO" does it?

    I wasn't sure "%8s" was safe, 'though I can't remember now why I
    thought it might not be.


    > BTW, an alternative would be to use
    >
    > printf( "%*s%c%*s", NAMLEN, NameArray[ 0 ].name, '.',
    > EXTLEN, NameArray[ 0 ].ext );
    > or
    > printf( "%*s%c%*s", sizeof NameArray->name, NameArray[ 0 ].name,

    '.',
    > sizeof NameArray->ext, NameArray[ 0 ].ext );



    Ah, "%*", _that's_ what I couldn't think of.


    >> Also, is there a way to get e.g.,
    >> sizeof NameExt.Ext
    >> (which doesn't work) at compile-time?

    >
    >
    > Yes, if you give sizeof the name of a real instance of the NameExt
    > struct, i.e.
    >
    > sizeof NameArray[ 0 ].ext
    > or
    > sizeof NameArray->ext
    >


    OK, I need to have that explained a bit more. Why does
    sizeof(int) work? It's not a "real instance". Is that the
    sizeof paren/no paren thing?

    Why does NameArray->ext work, without a specific array index?

    And I'm definitely confused by NameArray.ext, *NameArray.ext [or
    is that *(NameArray).ext?], and NameArray->ext. Could you kindly
    explain the differences? I know an array reference is (almost?)
    a pointer, but I don't know for structs.

    Thanks.

    --
    { Don't use the "altavista.net" reply-to; it's extinct, but I don't
    know how to change it in Google Groups. Use "comcast" instead of
    "altavista" if you want to email me. }
    gtippery, Feb 24, 2005
    #3
  4. gtippery

    -berlin.de Guest

    gtippery <> wrote:
    >>> #include <stdlib.h> /* for itoa */

    >>
    >> Sorry, but itoa() is an extension that you won't always find in
    >> <stdlib.h>.


    > Yeah, I had to dig a bit to even find it, in my compiler's library -
    > I guess it was "depreciated" even in 1993...


    It wasn't deprecated because it never was part of the set of functions
    the standard requires.

    >>> main()

    >>

    > ...
    >> you better make that either
    >>
    >> int main( void )
    >> or
    >> int main( int argc, char *argv[ ] )
    >>

    > Yup. I did that deliberately to provoke someone to answer.
    > <grin> That's gotta be either #1 or #2 on the 'most frequent"
    > list...


    You don't seem to have too good an opinion about clc;-)

    >> itoa() isn't a standard C function, so this will fail on systems
    >> where there's no itoa().


    > Do you suggest sprintf(), or is there a standard, specific
    > integer-to-characters function? BTW, do you know if itoa()
    > [or something equivalent] is not standardized because character
    > sets aren't, or is there some other reason?


    I don't know what itoa() would be good for since it only reproduces
    a functionality you already have with sprintf(). I guess someone
    invented it for symmetry reasons because there's atoi(), But atoi()
    is a rather useless function anyway and should be avoided in favour
    of strtol().

    >>> Particularly, are there easier ways to:
    >>> (1) initialize the NameArray records;


    > [Your corrected version requoted here for reference:]


    >> memcpy( &NameArray[0].name, "One ", NAMLEN );
    >> memcpy( &NameArray[0].ext, "1 ", EXTLEN );


    >> Perhaps, but that will depend on what you want to initialize the
    >> array elements with in the real case.


    > Well, for illustration purposes, is there a better way to do
    > what it _does_ do (setting an array-of-char field of a
    > structure to a text constant) than using memcpy()?


    I don't see any better way here.

    >> Since I don't know what findfirst() and
    >> findnext() return (they aren't standard C functions)


    > They're MS-DOS functions; in my library they return a pointer to
    > a structure full of binary values for file size, dates, etc.


    > What's the standard-C way to get the contents of a directory? I
    > have a few C reference books, but they date from the 1980's.
    > (And I wasn't around them when I originally posted.)


    There aren't any standard C functions, you must use the extensions
    for your OS - the word "directory" doesn't even appear anywhere in
    the C standard.

    >>> Also, is there a way to get e.g.,
    >>> sizeof NameExt.Ext
    >>> (which doesn't work) at compile-time?

    >>
    >>
    >> Yes, if you give sizeof the name of a real instance of the NameExt
    >> struct, i.e.
    >>
    >> sizeof NameArray[ 0 ].ext
    >> or
    >> sizeof NameArray->ext
    >>


    > OK, I need to have that explained a bit more. Why does
    > sizeof(int) work? It's not a "real instance". Is that the
    > sizeof paren/no paren thing?


    Yes, it is. Without the parentheses you can only use names of
    variables. If you want to use types they must be enclosed in
    parenthesis.

    > Why does NameArray->ext work, without a specific array index?


    Because NameArray is automatically taken here to be a pointer to
    the first element of the NameArray array (like when you pass an
    array to a function).

    > And I'm definitely confused by NameArray.ext, *NameArray.ext [or
    > is that *(NameArray).ext?], and NameArray->ext.


    When you have an array of structures like

    struct xyz {
    int x;
    char y;
    }

    struct xyz a[ 10 ];

    then 'a' "decays" in situations where it's used as a value into a
    pointer to the first element of the array. Thus 'a->y' is the same
    as 'a[0].y' (as is '(*a).y').

    > I know an array reference is (almost?) a pointer, but I don't know
    > for structs.


    It doesn't matter if you have an array of ints or structures or unions
    or function pointers or whatever, it's always the same. When the name
    of an array is used in a situation where it's used as if had a value
    (like in 'a->y') then it automatically is converted to a pointer to
    the first element of the array, no matter what kind of elements the
    array has. See also what Chris Torek calls "The Rule":

    http://web.torek.net/torek/c/index.html

    Regards, Jens
    --
    \ Jens Thoms Toerring ___ -berlin.de
    \__________________________ http://www.toerring.de
    -berlin.de, Feb 25, 2005
    #4
  5. gtippery

    gtippery Guest

    -berlin.de wrote:
    >
    > gtippery <> wrote:
    >>>> #include <stdlib.h> /* for itoa */

    >
    >>> Sorry, but itoa() is an extension that you won't always find in
    >>> <stdlib.h>.

    >> Yeah, I had to dig a bit to even find it, in my compiler's library -


    >> I guess it was "depreciated" even in 1993...

    >
    > It wasn't deprecated because it never was part of the set of

    functions
    > the standard requires.


    I meant "depreciated" by the distributor of the library; hence the
    quotes.


    > I don't know what itoa() would be good for since it only reproduces
    > a functionality you already have with sprintf(). I guess someone
    > invented it for symmetry reasons because there's atoi(), But atoi()
    > is a rather useless function anyway and should be avoided in favour
    > of strtol().
    >


    Most of the C library "reproduces a functionality you already have",
    but hopefully in a more convenient form. itoa()'s more convenient in
    an
    expression.


    >>>> Also, is there a way to get e.g.,
    >>>> sizeof NameExt.Ext
    >>>> (which doesn't work) at compile-time?


    (Requoting for context:)

    #define NAMLEN 8
    #define EXTLEN 3
    #define MAX 512

    typedef struct {
    char name[NAMLEN];
    char ext[EXTLEN];
    } NameExt;

    NameExt NameArray[MAX+1];
    int NameCnt=0;

    >
    >>> Yes, if you give sizeof the name of a real instance of the NameExt
    >>> struct, i.e.

    >
    >>> sizeof NameArray[ 0 ].ext
    >>> or
    >>> sizeof NameArray->ext

    >
    >
    >> OK, I need to have that explained a bit more. Why does
    >> sizeof(int) work? It's not a "real instance". Is that the
    >> sizeof paren/no paren thing?

    >
    >
    > Yes, it is. Without the parentheses you can only use names of
    > variables. If you want to use types they must be enclosed in
    > parenthesis.



    But 'sizeof(NameExt.Ext)' doesn't work either. Is NameExt.Ext a
    type, or what is it? It's certainly not a variable.

    >
    >> And I'm definitely confused by NameArray.ext, *NameArray.ext [or
    >> is that *(NameArray).ext?], and NameArray->ext.

    >
    >
    > When you have an array of structures like
    >
    > struct xyz {
    > int x;
    > char y;
    > }
    >
    > struct xyz a[ 10 ];
    >
    > then 'a' "decays" in situations where it's used as a value into a
    > pointer to the first element of the array. Thus 'a->y' is the same
    > as 'a[0].y' (as is '(*a).y').
    >


    What (if anything) would 'a.y' be?


    >> I know an array reference is (almost?) a pointer, but I don't know
    >> for structs.

    >
    > It doesn't matter if you have an array of ints or structures or

    unions
    > or function pointers or whatever, it's always the same. When the name


    > of an array is used in a situation where it's used as if had a value
    > (like in 'a->y') then it automatically is converted to a pointer to
    > the first element of the array, no matter what kind of elements the
    > array has. See also what Chris Torek calls "The Rule":
    >
    > http://web.torek.net/torek/c/index.html


    I didn't mean "for an array of structs", I meant "for structs", i.e.,
    in your example, is a reference to xyz (ever?) a pointer? From reading
    Torek's essay you pointed to, it appears it is not.

    Speaking of that essay, I'm still trying to digest it. Part of my
    problem is difficulty understanding C declarations, but I'm working
    on it.
    gtippery, Feb 27, 2005
    #5
  6. gtippery

    -berlin.de Guest

    gtippery <> wrote:
    >>>>> Also, is there a way to get e.g.,
    >>>>> sizeof NameExt.Ext
    >>>>> (which doesn't work) at compile-time?


    > (Requoting for context:)


    > #define NAMLEN 8
    > #define EXTLEN 3
    > #define MAX 512


    > typedef struct {
    > char name[NAMLEN];
    > char ext[EXTLEN];
    > } NameExt;


    > NameExt NameArray[MAX+1];
    > int NameCnt=0;


    >>>> Yes, if you give sizeof the name of a real instance of the NameExt
    >>>> struct, i.e.

    >>
    >>>> sizeof NameArray[ 0 ].ext
    >>>> or
    >>>> sizeof NameArray->ext

    >>
    >>> OK, I need to have that explained a bit more. Why does
    >>> sizeof(int) work? It's not a "real instance". Is that the
    >>> sizeof paren/no paren thing?

    >>
    >> Yes, it is. Without the parentheses you can only use names of
    >> variables. If you want to use types they must be enclosed in
    >> parenthesis.

    >
    > But 'sizeof(NameExt.Ext)' doesn't work either. Is NameExt.Ext a
    > type, or what is it? It's certainly not a variable.


    There are two things here. First of all there's nothing called
    "NameExt.Ext" at all, I guess you mean "NameExt.ext" but since
    you use the wrong spelling consistendly I am wondering. Second,
    and more important, "NameExt.ext" is neither a variable nor a
    type. The names of the elements of a structure aren't types but
    they are also not variables. So neither 'sizeof NameExt.ext' nor
    'sizeof(NameExt.ext)' can work. Therefore you're here forced to
    use a real instance of the structure to get at the size of its
    elements - at least I don't see any other way at the moment.

    >> When you have an array of structures like
    >>
    >> struct xyz {
    >> int x;
    >> char y;
    >> }
    >>
    >> struct xyz a[ 10 ];
    >>
    >> then 'a' "decays" in situations where it's used as a value into a
    >> pointer to the first element of the array. Thus 'a->y' is the same
    >> as 'a[0].y' (as is '(*a).y').
    >>

    > What (if anything) would 'a.y' be?


    That wouldn't make sense since 'a' isn't a structure (or union)
    but, when used in value context like here, a pointer to the first
    element of the array. And then the dot can't be used since a dot
    is only allowed after a structure (or union) variable name.

    >>> I know an array reference is (almost?) a pointer, but I don't know
    >>> for structs.

    >>
    >> It doesn't matter if you have an array of ints or structures or

    > unions
    >> or function pointers or whatever, it's always the same. When the name


    >> of an array is used in a situation where it's used as if had a value
    >> (like in 'a->y') then it automatically is converted to a pointer to
    >> the first element of the array, no matter what kind of elements the
    >> array has. See also what Chris Torek calls "The Rule":
    >>
    >> http://web.torek.net/torek/c/index.html


    > I didn't mean "for an array of structs", I meant "for structs", i.e.,
    > in your example, is a reference to xyz (ever?) a pointer? From reading
    > Torek's essay you pointed to, it appears it is not.


    Yes, in contrast to arrays, structures are "first class citizens" in C,
    so if you have the name of a structure variable without any adornments
    it means the whole structure and it's not converted to a pointer to
    the structure. So for something like

    struct xyz b;
    struct xyz a[10];
    some_func( b, a );

    'b' gets passed by value, i.e. a copy of the structure is passed to
    the function as with the basic types like ints etc., while for the
    array 'a' only a pointer to the array is what the function receives.
    And you can copy structures as a whole like in

    struct xyz b = { 42, 'a' };
    struct xyz c;
    c = b;

    which is something you also can't do with arrays.

    Regards, Jens
    --
    \ Jens Thoms Toerring ___ -berlin.de
    \__________________________ http://www.toerring.de
    -berlin.de, Feb 27, 2005
    #6
  7. gtippery

    Chris Torek Guest

    [Here is one of those older articles I was saving for a followup,
    found via references: lines in newer postings.]

    >gtippery <> wrote:
    >> (3) printf the NameArray array-of-char fields without explicitly
    >> converting them to strings?


    In article <>
    <-berlin.de> wrote:
    >You actually don't have to do that since you specify the length of them,
    >so even without the terminating '\0' characters it will work correctly.
    >You can safely do
    >
    > printf( fmtstr, NameArry[ 0 ].name, '.', NameArray[ 0 ].ext );
    >
    >when 'fmtstr' is e.g. "%8s%c%3s".


    This is almost, but not quite, right: you need "%.8s" to tell
    printf() that the corresponding "char *" value points to (the first
    element of) an array of size 8. "%8s" means "points to a \0-terminated
    string as usual, but print it in a field at least 8 characters
    wide":

    printf("%s.%s\n", "file", "c");

    prints "file.c\n", but:

    printf("%8s.%3s\n", "file", "c");

    prints " file. c\n". To get the blank-padding on the left, use
    the '-' flag:

    printf("%-8s.%-3s\n", "file", "c");

    prints "file .c \n".

    Of course, you can combine these, e.g.:

    printf("%-8.8s%c%-3.3s", name, '.', ext);

    would work.

    >BTW, an alternative would be to use
    >
    > printf( "%*s%c%*s", NAMLEN, NameArray[ 0 ].name, '.',
    > EXTLEN, NameArray[ 0 ].ext );
    >or
    > printf( "%*s%c%*s", sizeof NameArray->name, NameArray[ 0 ].name, '.',
    > sizeof NameArray->ext, NameArray[ 0 ].ext );


    Nit: "sizeof" produces a size_t value, but "%*" (and "%.*") require
    an int. Since printf() is variadic, a cast is appropriate here:

    printf("%.*s%c%.*s",
    (int)sizeof NameArray->name, NameArray[0].name, '.',
    (int)sizeof NameArray->ext, NameArray[0].ext);

    or:

    printf("%-*.*s%c%-*.*s",
    (int)sizeof NameArray->name, (int)sizeof NameArray->name,
    NameArray[0].name, '.',
    (int)sizeof NameArray->ext, (int)sizeof NameArray->ext,
    NameArray[0].ext);

    for instance. (I prefer the version with the NAMLEN and EXTLEN
    "#define"s, myself. Fewer casts make me happier. :) )
    --
    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, Feb 27, 2005
    #7
  8. On 21 Feb 2005 12:27:37 GMT, -berlin.de wrote:

    > gtippery <> wrote:
    > > Newbie-ish questions - I've been away from C for a _long_ time.


    <snip other comments I concur with>
    and add one minor one: double-slash comments are not standard in C90;
    they are in C99 and C++, and a pretty common extension in C90.

    > > (2) specify the format string, assuming I want to stick with constants
    > > for the field widths; and


    Aside from Jens' suggestion of sprintf (fmtstr, "%%%ds", NAMLEN) etc.,
    IF your lengths are #define'd as only an unsigned decimal literal --
    not anything else like say #define NAMLEN (128/16) -- you can
    stringize them into a constant string:
    #define XSTR(x) XSTR2(x) /* indirection to expand macro as arg */
    #define XSTR2(x) #x
    char fmtstr [] = "%" XSTR(NAMLEN) "s"; /* etc. */

    > > (3) printf the NameArray array-of-char fields without explicitly
    > > converting them to strings?

    >
    > You actually don't have to do that since you specify the length of them,
    > so even without the terminating '\0' characters it will work correctly.
    > You can safely do
    >
    > printf( fmtstr, NameArry[ 0 ].name, '.', NameArray[ 0 ].ext );
    >
    > when 'fmtstr' is e.g. "%8s%c%3s".
    >

    Wrong. %Ns specifies a _minimum_ width but the argument still must be
    null-terminated. %.Ns note the dot handles a nonterminated char array.

    > BTW, an alternative would be to use
    >
    > printf( "%*s%c%*s", NAMLEN, NameArray[ 0 ].name, '.',
    > EXTLEN, NameArray[ 0 ].ext );
    > or
    > printf( "%*s%c%*s", sizeof NameArray->name, NameArray[ 0 ].name, '.',
    > sizeof NameArray->ext, NameArray[ 0 ].ext );
    >

    Agree the first, but in the second the type of sizeof foo is size_t
    not int, and may not work correctly as a vararg. Cast it.

    Also I would write both the sizeof operand and the by-value argument
    as array.name for clarity -- -> is equvalent to [0]. but when
    reading it wastes time to verify it was used correctly in this case.

    - David.Thompson1 at worldnet.att.net
    Dave Thompson, Feb 28, 2005
    #8
  9. gtippery

    gtippery Guest

    I think you guys are scaring me. I'm half-expecting Brian or Dennis to
    chime in next with a correction to the correction to the corrections,
    and it appears I'm going to have to expand my vocabulary as well as my
    C skills.

    BTW, thanks for not asking, but yes, I *can* spell "standardize".
    <grin> Can I change the header without breaking the thread?
    gtippery, Mar 1, 2005
    #9
  10. gtippery

    gtippery Guest

    Dave Thompson wrote:
    > On 21 Feb 2005 12:27:37 GMT, -berlin.de wrote:
    >

    ....
    > Aside from Jens' suggestion of sprintf (fmtstr, "%%%ds", NAMLEN)

    etc.,
    > IF your lengths are #define'd as only an unsigned decimal literal --
    > not anything else like say #define NAMLEN (128/16) -- you can
    > stringize them into a constant string:
    > #define XSTR(x) XSTR2(x) /* indirection to expand macro as arg */
    > #define XSTR2(x) #x
    > char fmtstr [] = "%" XSTR(NAMLEN) "s"; /* etc. */


    I see how this is supposed to work, but not how it gets there with the
    indirection. Could you show me step by step how that expands, or
    possibly direct me to a good explanation of stringizing and pasting in
    macros? I've read about the "#" but didn't understand it.


    > > printf( "%*s%c%*s", sizeof NameArray->name, NameArray[ 0

    ].name, '.',
    > > sizeof NameArray->ext, NameArray[ 0 ].ext

    );
    > >

    > Agree the first, but in the second the type of sizeof foo is size_t
    > not int, and may not work correctly as a vararg. Cast it.
    >
    > Also I would write both the sizeof operand and the by-value argument
    > as array.name for clarity -- -> is equvalent to [0]. but when
    > reading it wastes time to verify it was used correctly in this case.
    >


    By "correctly" do you just mean that it refers to the same thing as the
    by-value argument, or some other sort of correctness?
    gtippery, Mar 10, 2005
    #10
  11. gtippery

    gtippery Guest

    With thanks to Jens, Chris, and David, here's the revised version.
    Besides recoding to the standard and simplifying, I attempted to
    make capitalization more consistent and MAXCOL a bit more obvious.
    I think it looks a lot better now. Does anything else need changing?


    #include <stdio.h>
    #include <string.h> /* for memcpy() */


    #define NAMLEN 8
    #define EXTLEN 3
    #define MAX 512
    #define MAXCOL 2


    typedef struct {
    char name[NAMLEN];
    char ext[EXTLEN];
    } NameExt;


    NameExt nameArray[MAX+1];
    int nameCnt=0;


    int main(void)
    {

    int i;
    int colnum = 0;


    /* Fill the array with (test) names & extensions,
    left-justified & space-filled (no '\0' characters). */

    memcpy( &nameArray[0].name, "One ", NAMLEN );
    memcpy( &nameArray[0].ext, "1 ", EXTLEN );

    memcpy( &nameArray[1].name, "TwoTwoTw", NAMLEN );
    memcpy( &nameArray[1].ext, "222", EXTLEN );

    memcpy( &nameArray[2].name, "333 ", NAMLEN );
    memcpy( &nameArray[2].ext, "003", EXTLEN );

    nameCnt = 3;


    /* Print names & extensions in multiple columns */

    for(i=0; i<nameCnt; i++) {
    printf("%-*.*s.%-*.*s",
    NAMLEN, NAMLEN, nameArray.name,
    EXTLEN, EXTLEN, nameArray.ext);

    /* Handle columnizing here */
    if(++colnum < MAXCOL) {
    printf(" ");
    } else {
    printf("\n");
    colnum = 0;
    }
    }
    printf("\n");

    }


    Two questions:

    1) Should I use a cast to (size_t) on the third parameter of the
    memcopy()'s? Does memcpy()'s prototype take care of that?

    2) Would

    "%-*.*s" "." "%-*.*s"

    be easier to read than

    "%-*.*s.%-*.*s"

    as the printf() format string?
    gtippery, Mar 10, 2005
    #11
  12. gtippery

    Michael Mair Guest

    gtippery wrote:
    > Dave Thompson wrote:
    >
    >>On 21 Feb 2005 12:27:37 GMT, -berlin.de wrote:
    >>

    >
    > ...
    >
    >>Aside from Jens' suggestion of sprintf (fmtstr, "%%%ds", NAMLEN)

    >
    > etc.,
    >
    >>IF your lengths are #define'd as only an unsigned decimal literal --
    >>not anything else like say #define NAMLEN (128/16) -- you can
    >>stringize them into a constant string:
    >>#define XSTR(x) XSTR2(x) /* indirection to expand macro as arg */
    >>#define XSTR2(x) #x
    >>char fmtstr [] = "%" XSTR(NAMLEN) "s"; /* etc. */

    >
    >
    > I see how this is supposed to work, but not how it gets there with the
    > indirection. Could you show me step by step how that expands, or
    > possibly direct me to a good explanation of stringizing and pasting in
    > macros? I've read about the "#" but didn't understand it.


    #x puts quotation marks around whatever x is:

    XSTR2(NAMLEN) gives you "NAMLEN".
    With #define NAMLEN 42,
    XSTR(NAMLEN) gives you XSTR2(42), i.e. "42"
    fmtstr thus becomes "%" "42" "s", equivalent to "%42s"

    >>> printf( "%*s%c%*s", sizeof NameArray->name, NameArray[ 0

    >
    > ].name, '.',
    >
    >>> sizeof NameArray->ext, NameArray[ 0 ].ext

    >
    > );
    >
    >>Agree the first, but in the second the type of sizeof foo is size_t
    >>not int, and may not work correctly as a vararg. Cast it.
    >>
    >>Also I would write both the sizeof operand and the by-value argument
    >>as array.name for clarity -- -> is equvalent to [0]. but when
    >>reading it wastes time to verify it was used correctly in this case.

    >
    > By "correctly" do you just mean that it refers to the same thing as the
    > by-value argument, or some other sort of correctness?


    IMO, you are referring to the second "correctly".
    If you see
    "*s", (int) sizeof array.name, array.name
    you know that the field width and the string fit together whereas
    "*s", (int) sizeof array->name, array.name
    makes you think for a moment whether this is correct.


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
    Michael Mair, Mar 10, 2005
    #12
  13. gtippery wrote:
    > Newbie-ish questions - I've been away from C for a _long_ time.
    >
    > It seems to me that there ought to be easier (or at least shorter)

    ways
    > to do what this does.


    <large snip>

    Well, here's something shorter and more similar to what you'd encounter
    in practice. For something like this, not many people are going to
    #define the size of the members of struct NameExt, since you can get at
    them with sizeof. Also, many times people are going to use a sentinel
    value to signal the end of the array rather than maintain a separate
    variable to do so.

    "(i + 1) % MAXCOL" is marginally idiomatic for producing columned
    output in situations where MAXCOL is a power of two or "small enough"
    for the compiler to play fancy tricks with.


    ---snip---
    #include <stdio.h>

    #define MAXCOL 2

    struct NameExt
    {
    char name[9];
    char ext[4];
    };


    int main(void)
    {
    /* Note sentinel at end */
    struct NameExt list[] = {
    { "BillyBob", "123" },
    { "Steve", "456" },
    { "Tom", "789" },
    { "Joe", "012" },
    { "Sal", "345" },
    { "", "" },
    };

    /* Print the array out */
    size_t i;
    for(i = 0; *list.name; i++)
    printf("%-*s%-*s%s",
    sizeof(list.name), list.name,
    sizeof(list.ext), list.ext,
    (i + 1) % MAXCOL ? "" : "\n");

    return 0;
    }
    ---snip---

    [mark@icepick ~]$ gcc -Wall -O2 -ansi -pedantic foo.c -o foo
    [mark@icepick ~]$ ./foo
    BillyBob 123 Steve 456
    Tom 789 Joe 012
    Sal 345
    [mark@icepick ~]$


    Mark F. Haigh
    Mark F. Haigh, Mar 11, 2005
    #13
  14. gtippery

    gtippery Guest

    Mark F. Haigh wrote:

    > Well, here's something shorter and more similar to what you'd

    encounter
    > in practice. For something like this, not many people are going to
    > #define the size of the members of struct NameExt, since you can get

    at
    > them with sizeof. Also, many times people are going to use a

    sentinel
    > value to signal the end of the array rather than maintain a separate
    > variable to do so.
    >


    I don't see any particular advantage either way on either of these
    changes:
    -- See an earlier posting for another opinion on #define's vs.
    casting sizeof's to int's for printf; and there may be other places
    that need to use the values.
    -- A sentinel's easier if you're using pointers (or doing
    comparisons), but what's its advantage if you're indexing? And that's
    assuming the count's not needed for anything else, of course.

    > "(i + 1) % MAXCOL" is marginally idiomatic for producing columned
    > output in situations where MAXCOL is a power of two or "small enough"
    > for the compiler to play fancy tricks with.
    >


    What kind of "tricks" did you have in mind that the compiler might do
    with, say, 5 columns per line? Isn't it either going to have to divide
    or to maintain an internal modulo counter (like I'm doing explicitly)?

    I used a separate column counter have the column # directly available
    for other purposes (not shown) and debugging. Also, there are
    additional fields in each column in the working program, so putting the
    column logic separately seemed easier. I _will_ see if I can use the
    %s / ? combo.

    The rest of your code doesn't quite do the same thing as mine - the
    "input" data's formatted differently and so's the output.

    If you just wanted to show something similar, that's fine, and it was
    interesting. But the reason I didn't use an array of strings in the
    first place is that in the real program, the data's coming from an
    existing packed data structure in memory (returned by the OS), and
    would have to be converted to strings to use your sentinel and printing
    techniques; so as far as I can see I'd need the memcpy()'s anyway.

    Then to get the right output, it needs the changes I show below to
    allow for the fact that the structure members now each include '\0'.
    Also, the array's larger now (by two bytes per element), but that won't
    actually be a problem in my case.

    >
    > ---snip---
    > #include <stdio.h>
    >
    > #define MAXCOL 2
    >
    > struct NameExt
    > {
    > char name[9];
    > char ext[4];
    > };
    >
    >
    > int main(void)
    > {
    > /* Note sentinel at end */
    > struct NameExt list[] = {
    > { "BillyBob", "123" },
    > { "Steve", "456" },
    > { "Tom", "789" },
    > { "Joe", "012" },
    > { "Sal", "345" },
    > { "", "" },
    > };
    >
    > /* Print the array out */
    > size_t i;


    What's the reason for using size_t instead of just int? I don't see
    anywhere you use i as a size.

    > for(i = 0; *list.name; i++)


    *list.name is the same as list.name[0], right? You're checking
    if the first char is zero?

    > printf("%-*s%-*s%s",


    printf("%-*s.%-*s%s",

    > sizeof(list.name), list.name,
    > sizeof(list.ext), list.ext,


    (int)sizeof(list.name) - 1, list.name,
    (int)sizeof(list.ext) - 1, list.ext,

    > (i + 1) % MAXCOL ? "" : "\n");


    (i + 1) % MAXCOL ? " " : "\n");

    >
    > return 0;


    I've been meaning to ask about that. Older references seem to imply
    that main() defaults to returning 0, and I haven't seen anything newer
    that says differently, but I wouldn't be surprised. I downloaded a
    copy of a "late draft" of the spec, but it was a .bz and I couldn't
    open it. 8(

    > }
    > ---snip---
    >
    > [mark@icepick ~]$ gcc -Wall -O2 -ansi -pedantic foo.c -o foo
    > [mark@icepick ~]$ ./foo
    > BillyBob 123 Steve 456
    > Tom 789 Joe 012
    > Sal 345
    > [mark@icepick ~]$
    >


    Should look like this:

    BillyBob.123 Steve .456
    Tom .789 Joe .012
    Sal .345

    >
    > Mark F. Haigh
    >
    gtippery, Mar 11, 2005
    #14
  15. gtippery

    gtippery Guest

    Michael Mair wrote:
    ....
    > #x puts quotation marks around whatever x is:
    >
    > XSTR2(NAMLEN) gives you "NAMLEN".
    > With #define NAMLEN 42,
    > XSTR(NAMLEN) gives you XSTR2(42), i.e. "42"
    > fmtstr thus becomes "%" "42" "s", equivalent to "%42s"
    >


    OK, thanks. Is the indirection necessary to avoid getting a literal
    "#" instead?

    ....
    > >
    > >>Agree the first, but in the second the type of sizeof foo is size_t
    > >>not int, and may not work correctly as a vararg. Cast it.
    > >>
    > >>Also I would write both the sizeof operand and the by-value

    argument
    > >>as array.name for clarity -- -> is equvalent to [0]. but when
    > >>reading it wastes time to verify it was used correctly in this

    case.
    > >
    > > By "correctly" do you just mean that it refers to the same thing as

    the
    > > by-value argument, or some other sort of correctness?

    >
    > IMO, you are referring to the second "correctly".


    Yes. Sorry for the ambiguity.

    > If you see
    > "*s", (int) sizeof array.name, array.name
    > you know that the field width and the string fit together whereas
    > "*s", (int) sizeof array->name, array.name
    > makes you think for a moment whether this is correct.
    >


    Thanks, that's what I thought.
    gtippery, Mar 11, 2005
    #15
  16. gtippery wrote:
    > Mark F. Haigh wrote:
    >


    <large snip>

    > If you just wanted to show something similar, that's fine, and it was
    > interesting. But the reason I didn't use an array of strings in the
    > first place is that in the real program, the data's coming from an
    > existing packed data structure in memory (returned by the OS), and
    > would have to be converted to strings to use your sentinel and

    printing
    > techniques; so as far as I can see I'd need the memcpy()'s anyway.


    And how was I supposed to know this? State this up front next time.
    I'd thought it was for some kind of class project (first name / 3 digit
    telephone extension), and that you had poor taste in data structures
    and compilers.

    I'll take another look when I get some time. Disregard the previous
    post, and note:

    1. Yes, you should cast size_t to int if it's going to be going
    through the default argument promotions. I shouldn't have posted so
    hastily right before bedtime (on some days, my only time for c.l.c).
    Shame on me.

    2. There are all kinds of dirty tricks and pre-canned "divide by x"
    code sequences for compiler writers. Look at "Hacker's Delight" by
    Henry S. Warren Jr. for more info on some interesting tricks (magic
    numbers, etc).

    3. What's the biggest number of elements that your array can have?
    Check your platform docs. It may be more than int can handle, but less
    than or equal to what size_t can handle.

    4. Always put a return statement in main. It's necessary in C89, and
    good style in C99.


    Mark F. Haigh
    Mark F. Haigh, Mar 12, 2005
    #16
  17. gtippery

    CBFalconer Guest

    gtippery wrote:
    >

    .... snip ...
    >
    > I've been meaning to ask about that. Older references seem to imply
    > that main() defaults to returning 0, and I haven't seen anything newer
    > that says differently, but I wouldn't be surprised. I downloaded a
    > copy of a "late draft" of the spec, but it was a .bz and I couldn't
    > open it. 8(


    Sounds like you got it from me. You just have to feed it to bzip2
    to expand it. Execute "bzip2 -dc n869_txt.bz2" and n869.txt will
    magically appear. However you got it over a 56k modem in about 2
    minutes instead of about 9 minutes, due to the compressions. A zip
    version would have taken about 3 minutes.

    Google for bzip2, and keep it available. You can find it for most
    systems.

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
    CBFalconer, Mar 12, 2005
    #17
  18. gtippery

    gtippery Guest

    CBFalconer wrote:
    > gtippery wrote:
    > >

    > ... snip ...
    > > I downloaded a
    > > copy of a "late draft" of the spec, but it was a .bz and I couldn't
    > > open it. 8(

    >
    > Sounds like you got it from me.


    Yup. Lots of other interesting stuff you have there, btw. I'm going
    to dig throught that Borland/ISO-input thing when I can.

    > You just have to feed it to bzip2
    > to expand it. Execute "bzip2 -dc n869_txt.bz2" and n869.txt will
    > magically appear. However you got it over a 56k modem in about 2
    > minutes instead of about 9 minutes, due to the compressions. A zip
    > version would have taken about 3 minutes.
    >


    Well, actually I got it in about 5 seconds (cable modem). Guess it
    saved me, oh, maybe 1 or 2 seconds vs. zip... <grin>
    gtippery, Mar 12, 2005
    #18
  19. gtippery

    Michael Mair Guest

    gtippery wrote:
    > Michael Mair wrote:
    > ...
    >
    >>#x puts quotation marks around whatever x is:
    >>
    >> XSTR2(NAMLEN) gives you "NAMLEN".
    >>With #define NAMLEN 42,
    >> XSTR(NAMLEN) gives you XSTR2(42), i.e. "42"
    >>fmtstr thus becomes "%" "42" "s", equivalent to "%42s"

    >
    > OK, thanks. Is the indirection necessary to avoid getting a literal
    > "#" instead?


    [For the record, I quote the definitions of XSTR and XSTR2:
    #define XSTR(x) XSTR2(x) /* indirection to expand macro as arg */
    #define XSTR2(x) #x
    ]

    Nope. Have a look at the direct call to XSTR2:
    XSTR2(42) gives you "42", as expected
    but
    XSTR2(SOME_MACRO_EXPRESSION) gives you "SOME_MACRO_EXPRESSION"
    instead of whatever SOME_MACRO_EXPRESSION expands to. In the
    above case, in order to get the 42 "out of" NAMLEN, we need the
    indirection. XSTR(NAMLEN) expands NAMLEN (to 42) before
    XSTR2(expansion of NAMLEN) is applied. Thus, XSTR(NAMLEN) gives
    you "42".


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
    Michael Mair, Mar 12, 2005
    #19
  20. gtippery

    gtippery Guest

    Mark F. Haigh wrote:
    > gtippery wrote:
    > > Mark F. Haigh wrote:
    > >

    >
    > <large snip>
    >
    > > If you just wanted to show something similar, that's fine, and it

    was
    > > interesting. But the reason I didn't use an array of strings in

    the
    > > first place is that in the real program, the data's coming from an
    > > existing packed data structure in memory (returned by the OS), and
    > > would have to be converted to strings to use your sentinel and

    > printing
    > > techniques; so as far as I can see I'd need the memcpy()'s anyway.

    >
    > And how was I supposed to know this? State this up front next time.


    The "real app" is mentioned in the original post (in a comment).
    Anyway, I wasn't objecting, just explaining.

    > I'd thought it was for some kind of class project (first name / 3

    digit
    > telephone extension), and that you had poor taste in data structures
    > and compilers.


    Well, "de gustibus non est disputandum", and I've no reason to think
    mine's particularly good. The compiler choice is partially dictated by
    the target system, which runs PC-DOS 6. I've also got Borland's
    compiler, but it seemed like overkill. PowerC, as far as I've seen to
    date, has all the C89 features except localization (if that's strictly
    C89). It may not be "picky" enough -- I need to check the options in
    the docs.

    >

    ....
    > I'll take another look when I get some time. Disregard the previous
    > post, and note:
    >
    > 1. Yes, you should cast size_t to int if it's going to be going
    > through the default argument promotions.


    I learned this from an earlier post in this same thread, myself.

    > 2. There are all kinds of dirty tricks and pre-canned "divide by x"
    > code sequences for compiler writers. Look at "Hacker's Delight" by
    > Henry S. Warren Jr. for more info on some interesting tricks (magic
    > numbers, etc).
    >


    Noted.

    > 3. What's the biggest number of elements that your array can have?
    > Check your platform docs. It may be more than int can handle, but

    less
    > than or equal to what size_t can handle.
    >


    The platform limit is 64KB for any one item (i8086). The array would
    be the limiting factor in this case (at something over 5,000 elements),
    but it's never going to get that big - the maximum dimension is 512.

    If size_t isn't actually an int (of some standard type), isn't that
    going to be a problem in the for()? I thought the index variable had
    to be an integer or enumeration.

    > 4. Always put a return statement in main. It's necessary in C89,

    and
    > good style in C99.

    ....

    Thanks.
    gtippery, Mar 12, 2005
    #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. KK
    Replies:
    2
    Views:
    516
    Big Brian
    Oct 14, 2003
  2. mclaugb
    Replies:
    4
    Views:
    2,259
    Robert Kern
    Jan 21, 2007
  3. Daniel T.

    Optimize this please?

    Daniel T., Nov 29, 2006, in forum: C++
    Replies:
    13
    Views:
    532
    kwikius
    Nov 29, 2006
  4. TF
    Replies:
    10
    Views:
    725
    =?Utf-8?B?U2VyZ2V5IFBvYmVyZXpvdnNraXk=?=
    Jun 28, 2007
  5. please help optimize sub

    , Oct 18, 2007, in forum: Perl Misc
    Replies:
    16
    Views:
    180
Loading...

Share This Page