What is wrong with this code?

Discussion in 'C Programming' started by Bill Reid, May 13, 2007.

  1. Bill Reid

    Bill Reid Guest

    #define MAX_VALUES 64

    typedef struct {
    unsigned value_1;
    double value_2;
    double value_3;
    double value_4;
    } VALUES;

    typedef struct {
    unsigned num_values;
    unsigned tot_value_1;
    double tot_value_2;
    double tot_value_3;
    double tot_value_4;
    VALUES values[MAX_VALUES];
    } VALUES_STRUCT;

    VALUES_STRUCT values_struct=
    {3,0,0.0,0.0,0.0,{{1,1.0,1.0,1.0},{1,1.0,1.0,1.0},{1,1.0,1.0,1.0}}};

    double add_double_numbers
    (void *number,unsigned num_numbers,unsigned inc_size) {
    void *void_ptr=NULL;
    char *inc_ptr=number;
    double *double_ptr=NULL;
    unsigned number_num=0;
    double total=0.0;

    while(number_num<num_numbers) {
    void_ptr=inc_ptr;
    double_ptr=void_ptr;
    total+=*double_ptr;
    inc_ptr+=inc_size;
    number_num++;
    }

    return total;
    }

    void add_value_4(void) {

    values_struct.tot_value_4=add_double_numbers
    (&values_struct.values[0].value_4,values_struct.num_values,
    sizeof(VALUES));

    printf("\nThe total is %f",values_struct.tot_value_4);
    }

    int main(void) {

    add_value_4();

    return 0;
    }

    ---
    William Ernest Reid
     
    Bill Reid, May 13, 2007
    #1
    1. Advertising

  2. In article <3eI1i.144346$>,
    Bill Reid <> wrote:

    >#define MAX_VALUES 64


    You fail to include <stdio.h>, which would affect the interpretation
    of printf(), possibly causing garbage values to be printed out.

    Other than that: what is the difference between the output you
    see and the output you expect?
    --
    There are some ideas so wrong that only a very intelligent person
    could believe in them. -- George Orwell
     
    Walter Roberson, May 13, 2007
    #2
    1. Advertising

  3. Bill Reid

    Default User Guest

    Bill Reid wrote:


    Why do you think there's something wrong with it? Did it fail to
    compile? Did it get different results than you expected?




    Brian
     
    Default User, May 13, 2007
    #3
  4. Bill Reid

    Bill Reid Guest

    Walter Roberson <-cnrc.gc.ca> wrote in message
    news:f27kud$50$...
    > In article <3eI1i.144346$>,
    > Bill Reid <> wrote:
    >
    > You fail to include <stdio.h>, which would affect the interpretation
    > of printf(), possibly causing garbage values to be printed out.
    >

    Uh, yeah, for me on this compiler, just a warning, I think. I haven't
    actually compiled the actual code I posted, just similar stuff...

    > Other than that: what is the difference between the output you
    > see and the output you expect?


    I get exactly what I expect. Honestly, I was looking for some
    type of criticism of the general approach for accessing structure
    elements in add_double_numbers(), that's all.

    > There are some ideas so wrong that only a very intelligent person
    > could believe in them. -- George Orwell


    That is precisely the point, that is precisely the point. Here, let's
    try again...what is wrong with this code?

    #include <stdio.h> /* !!!!!!!!!!!! */

    #define MAX_VALUES 64

    typedef struct {
    unsigned value_1;
    double value_2;
    double value_3;
    double value_4;
    } VALUES;

    typedef struct {
    unsigned num_values;
    unsigned tot_value_1;
    double tot_value_2;
    double tot_value_3;
    double tot_value_4;
    VALUES values[MAX_VALUES];
    } VALUES_STRUCT;

    VALUES_STRUCT values_struct=
    {3,0,0.0,0.0,0.0,{{1,1.0,1.0,1.0},{1,1.0,1.0,1.0},{1,1.0,1.0,1.0}}};

    double add_double_numbers
    (void *number,unsigned num_numbers,unsigned inc_size) {
    void *void_ptr=NULL;
    char *inc_ptr=number;
    double *double_ptr=NULL;
    unsigned number_num=0;
    double total=0.0;

    while(number_num<num_numbers) {
    void_ptr=inc_ptr;
    double_ptr=void_ptr;
    total+=*double_ptr;
    inc_ptr+=inc_size;
    number_num++;
    }

    return total;
    }

    void add_value_4(void) {

    values_struct.tot_value_4=add_double_numbers
    (&values_struct.values[0].value_4,values_struct.num_values,
    sizeof(VALUES));

    printf("\nThe total is %f",values_struct.tot_value_4);
    }

    int main(void) {

    add_value_4();

    return 0;
    }

    ---
    William Ernest Reid
     
    Bill Reid, May 13, 2007
    #4
  5. Bill Reid said:

    >
    > Walter Roberson <-cnrc.gc.ca> wrote in message
    > news:f27kud$50$...
    >> In article
    >> <3eI1i.144346$>, Bill
    >> Reid <> wrote:
    >>
    >> You fail to include <stdio.h>, which would affect the interpretation
    >> of printf(), possibly causing garbage values to be printed out.
    >>

    > Uh, yeah, for me on this compiler, just a warning, I think.


    No such thing. It's not "just a warning". It's a warning.

    > I haven't
    > actually compiled the actual code I posted, just similar stuff...


    ....removing the last vestiges of a point from this entire thread.

    --
    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, May 13, 2007
    #5
  6. Bill Reid

    Chris Torek Guest

    In article <bCK1i.144938$>
    Bill Reid <> wrote:
    >I get exactly what I expect. Honestly, I was looking for some
    >type of criticism of the general approach for accessing structure
    >elements in add_double_numbers(), that's all.


    [where the add_double_numbers routine is]

    >double add_double_numbers
    >(void *number,unsigned num_numbers,unsigned inc_size) {
    > void *void_ptr=NULL;
    > char *inc_ptr=number;
    > double *double_ptr=NULL;
    > unsigned number_num=0;
    > double total=0.0;
    >
    > while(number_num<num_numbers) {
    > void_ptr=inc_ptr;
    > double_ptr=void_ptr;
    > total+=*double_ptr;
    > inc_ptr+=inc_size;
    > number_num++;
    > }
    >
    > return total;
    > }


    Oh ... in that case, as far as I can tell, the code is valid. It
    does seem "slightly dangerous" (in the sense that it would be easy
    for a caller to provide improper arguments, and then have everything
    go kaboom). Also, while we tend to discourage casts in comp.lang.c,
    I would probably go ahead and use them here, and make a few other
    minor changes:

    /*
    * Iterate over some kind of array, which may be an array of structures
    * or array of arrays, in which there is at least one "double" element.
    * Add up the n "double" elements that are spaced apart by
    * "inc_size" bytes, given a pointer to the first such "double".
    */
    double add_double_numbers(double *first, size_t n, size_t inc_size) {
    unsigned char *p; /* will point to our various "double"s */
    double total = 0.0;
    size_t i;

    p = (unsigned char *)first;
    for (i = 0; i < n; i++) {
    total += *(double *)p;
    p += inc_size;
    }
    return total;
    }

    The loop could be compressed to:

    for (p = (unsigned char *)first, i = 0; i < n; p += inc_size, i++)
    total += *(double *)p;

    for those who prefer to see all the loop invariants in the "for"
    expressions.

    The reason for taking a "double *" is to force the caller to
    pass the address of the first "double" element in the array of
    structures, in case the caller wants to do something like:

    struct S {
    int a;
    double x;
    char *b;
    FILE *c;
    /* etc */
    };
    struct S arr[SIZE];
    double result;
    ...
    result = add_double_numbers(<args here to total up "arr">);

    which in this case should be:

    result = add_double_numbers(&arr[0].x, SIZE, sizeof arr[0]);

    and *not*:

    result = add_double_numbers(&arr[0], SIZE, sizeof arr[0]); /*WRONG*/

    (Note that you could actually make the latter work by passing not
    only a "byte spacing from double to double", i.e., inc_size, but
    also an "offset from base to first double" element. There is
    no real need, in this case: we can just include the offset in
    the first argument. Some might like the symmetry of &arr[0] and
    sizeof arr[0], though, in which case, add one more argument,
    offsetof(arr[0], x), and change the first formal parameter to
    "void *base" and make the other obvious required changes.)
    --
    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, May 13, 2007
    #6
  7. "Bill Reid" <> writes:
    > Walter Roberson <-cnrc.gc.ca> wrote in message
    > news:f27kud$50$...
    >> In article <3eI1i.144346$>,
    >> Bill Reid <> wrote:
    >>
    >> You fail to include <stdio.h>, which would affect the interpretation
    >> of printf(), possibly causing garbage values to be printed out.
    >>

    > Uh, yeah, for me on this compiler, just a warning, I think.


    If you use functions declared in <stdio.h>, the "#include <stdio.h>"
    directive is not optional. Your compiler might not do you the favor
    of rejecting your program, but you need to add it anyway.

    (There are some cases where the "#include" isn't actually mandatory as
    far as the language standard is concerned, but there is no reason at
    all not to add it.)

    > I haven't
    > actually compiled the actual code I posted, just similar stuff...

    [...]

    Well, if it's not worth your time to compile your code before posting
    it, it's certainly not worth my time to look at it. Let us know when
    you have a serious question.

    > I get exactly what I expect. Honestly, I was looking for some
    > type of criticism of the general approach for accessing structure
    > elements in add_double_numbers(), that's all.


    Then it would have been useful to say so. Asking "What is wrong with
    this code?" (and that only in the subject header; it needs to be in
    the body of your article) isn't particularly helpful.

    We're glad to answer questions, but you need to take the time to ask
    them.

    --
    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."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, May 13, 2007
    #7
  8. In article <3eI1i.144346$>,
    Bill Reid <> wrote:

    >typedef struct {
    > unsigned value_1;
    > double value_2;
    > double value_3;
    > double value_4;
    > } VALUES;
    >
    >typedef struct {
    > unsigned num_values;
    > unsigned tot_value_1;
    > double tot_value_2;
    > double tot_value_3;
    > double tot_value_4;
    > VALUES values[MAX_VALUES];
    > } VALUES_STRUCT;


    To avoid replicating the fields here, you could do

    typedef struct {
    unsigned num_values;
    VALUES total[MAX_VALUES];
    VALUES values[MAX_VALUES];
    } VALUES_STRUCT;

    and refer to v.total.value1 instead of v.tot_value_1, etc.

    >double add_double_numbers
    >(void *number,unsigned num_numbers,unsigned inc_size) {
    > void *void_ptr=NULL;
    > char *inc_ptr=number;
    > double *double_ptr=NULL;
    > unsigned number_num=0;
    > double total=0.0;
    >
    > while(number_num<num_numbers) {
    > void_ptr=inc_ptr;
    > double_ptr=void_ptr;
    > total+=*double_ptr;
    > inc_ptr+=inc_size;
    > number_num++;
    > }
    >
    > return total;
    > }


    I would prefer something like:

    double add_double_numbers(double *base, size_t count, size_t stride)
    {
    unsigned char *byte_ptr = (unsigned char *)base;
    unsigned i;
    double total=0.0;

    for(i=0; i<count; i++)
    {
    total += *(double *)byte_ptr;
    byte_ptr += stride;
    }

    return total;
    }

    Since the function only works for doubles, you gain nothing by making
    the argument void *; use double * to emphasise its meaning.

    size_t is the right type for object counts and sizes (cf calloc()).

    I prefer my variable names; others may disagree. ("Stride" is a
    standard term for this sort of distance between successive elements.)

    There's no need to use both void and char pointers; converting a
    correctly aligned pointer to and from a char pointer is guaranteed to
    work. "Char" would be just as correct as "unsigned char" but the
    latter is perhaps better for generic byte pointers.

    Using a cast in the accumulating expression instead of an extra
    variable and assignment might not be to everyone's taste, but reducing
    the vertical size of a function aids readability in my opinion.

    When a loop is over a sequence of integers, a for loop is clearer than
    a while loop.

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
     
    Richard Tobin, May 13, 2007
    #8
  9. In article <f280o9$g5l$>, I wrote:

    >double add_double_numbers(double *base, size_t count, size_t stride)
    >{
    > unsigned char *byte_ptr = (unsigned char *)base;
    > unsigned i;


    That should have been "size_t i;".

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
     
    Richard Tobin, May 13, 2007
    #9
  10. Bill Reid

    Bill Reid Guest

    Chris Torek <> wrote in message
    news:...
    > In article <bCK1i.144938$>
    > Bill Reid <> wrote:


    > >I get exactly what I expect. Honestly, I was looking for some
    > >type of criticism of the general approach for accessing structure
    > >elements in add_double_numbers(), that's all.

    >
    > [where the add_double_numbers routine is]
    >
    > >double add_double_numbers
    > >(void *number,unsigned num_numbers,unsigned inc_size) {
    > > void *void_ptr=NULL;
    > > char *inc_ptr=number;
    > > double *double_ptr=NULL;
    > > unsigned number_num=0;
    > > double total=0.0;
    > >
    > > while(number_num<num_numbers) {
    > > void_ptr=inc_ptr;
    > > double_ptr=void_ptr;
    > > total+=*double_ptr;
    > > inc_ptr+=inc_size;
    > > number_num++;
    > > }
    > >
    > > return total;
    > > }

    >
    > Oh ... in that case, as far as I can tell, the code is valid. It
    > does seem "slightly dangerous" (in the sense that it would be easy
    > for a caller to provide improper arguments, and then have everything
    > go kaboom).


    Yes, but I tend to use stuff like this in my REALLY fundamental
    "deep" libraries, and usually the only stuff that touches it are essentially
    slightly higher-level more specific-purpose libraries. I'm trading off
    a little "danger" for shrinking my total code-base by eliminating as
    much redundant (except for the function signature) simplistic functionality
    as possible...

    > Also, while we tend to discourage casts in comp.lang.c,
    > I would probably go ahead and use them here, and make a few other
    > minor changes:
    >

    OK, THIS is what I'm looking for, an ACTUAL discussion of
    real-world practical "standard C" here...

    > /*
    > * Iterate over some kind of array, which may be an array of structures
    > * or array of arrays, in which there is at least one "double" element.
    > * Add up the n "double" elements that are spaced apart by
    > * "inc_size" bytes, given a pointer to the first such "double".
    > */


    Yup, that's it in a nutshell, except I use this basic approach for
    integers, long doubles, chars, whatever (the classic and most
    straightforward
    is how I generate menu item lists for either GUI or "console" applications
    from an array of structures that describe the routine parameters, function
    pointers, etc., which also include a menu item text string somewhere
    in the mix, by calling a single function signature "make_menu_list()" for
    any
    type of identifiable class of routines).

    > double add_double_numbers(double *first, size_t n, size_t inc_size) {
    > unsigned char *p; /* will point to our various "double"s */
    > double total = 0.0;
    > size_t i;
    >
    > p = (unsigned char *)first;
    > for (i = 0; i < n; i++) {
    > total += *(double *)p;
    > p += inc_size;
    > }
    > return total;
    > }
    >

    Let me substitute that in my little test library and see what happens...

    > The loop could be compressed to:
    >
    > for (p = (unsigned char *)first, i = 0; i < n; p += inc_size, i++)
    > total += *(double *)p;
    >
    > for those who prefer to see all the loop invariants in the "for"
    > expressions.
    >

    A lot of times, that's me, but in many of the actual cases, I'm doing
    SIGNIFICANTLY more processing in the loop, so it ain't going down
    to two lines in those cases...

    > The reason for taking a "double *" is to force the caller to
    > pass the address of the first "double" element in the array of
    > structures, in case the caller wants to do something like:
    >
    > struct S {
    > int a;
    > double x;
    > char *b;
    > FILE *c;
    > /* etc */
    > };
    > struct S arr[SIZE];
    > double result;
    > ...
    > result = add_double_numbers(<args here to total up "arr">);
    >
    > which in this case should be:
    >
    > result = add_double_numbers(&arr[0].x, SIZE, sizeof arr[0]);
    >
    > and *not*:
    >
    > result = add_double_numbers(&arr[0], SIZE, sizeof arr[0]); /*WRONG*/
    >
    > (Note that you could actually make the latter work by passing not
    > only a "byte spacing from double to double", i.e., inc_size, but
    > also an "offset from base to first double" element. There is
    > no real need, in this case: we can just include the offset in
    > the first argument. Some might like the symmetry of &arr[0] and
    > sizeof arr[0], though, in which case, add one more argument,
    > offsetof(arr[0], x), and change the first formal parameter to
    > "void *base" and make the other obvious required changes.)


    OK, let me play around with this stuff a little, thanks...

    ---
    William Ernest Reid
     
    Bill Reid, May 14, 2007
    #10
  11. Bill Reid

    Bill Reid Guest

    Richard Tobin <> wrote in message
    news:f280o9$g5l$...
    > In article <3eI1i.144346$>,
    > Bill Reid <> wrote:
    >
    > >typedef struct {
    > > unsigned value_1;
    > > double value_2;
    > > double value_3;
    > > double value_4;
    > > } VALUES;
    > >
    > >typedef struct {
    > > unsigned num_values;
    > > unsigned tot_value_1;
    > > double tot_value_2;
    > > double tot_value_3;
    > > double tot_value_4;
    > > VALUES values[MAX_VALUES];
    > > } VALUES_STRUCT;

    >
    > To avoid replicating the fields here, you could do
    >
    > typedef struct {
    > unsigned num_values;
    > VALUES total[MAX_VALUES];
    > VALUES values[MAX_VALUES];
    > } VALUES_STRUCT;
    >
    > and refer to v.total.value1 instead of v.tot_value_1, etc.
    >
    > >double add_double_numbers
    > >(void *number,unsigned num_numbers,unsigned inc_size) {
    > > void *void_ptr=NULL;
    > > char *inc_ptr=number;
    > > double *double_ptr=NULL;
    > > unsigned number_num=0;
    > > double total=0.0;
    > >
    > > while(number_num<num_numbers) {
    > > void_ptr=inc_ptr;
    > > double_ptr=void_ptr;
    > > total+=*double_ptr;
    > > inc_ptr+=inc_size;
    > > number_num++;
    > > }
    > >
    > > return total;
    > > }

    >
    > I would prefer something like:
    >
    > double add_double_numbers(double *base, size_t count, size_t stride)
    > {
    > unsigned char *byte_ptr = (unsigned char *)base;
    > unsigned i;
    > double total=0.0;
    >
    > for(i=0; i<count; i++)
    > {
    > total += *(double *)byte_ptr;
    > byte_ptr += stride;
    > }
    >
    > return total;
    > }
    >
    > Since the function only works for doubles, you gain nothing by making
    > the argument void *; use double * to emphasise its meaning.
    >

    OK, that's a good point, my problem is that I'm not that clever at
    writing "C" code, so let me try this out and see how it works...

    > size_t is the right type for object counts and sizes (cf calloc()).
    >

    Yes, although in most all cases I don't think I'll be exceeding
    an unsigned...

    > I prefer my variable names; others may disagree. ("Stride" is a
    > standard term for this sort of distance between successive elements.)
    >

    Never really heard of it...

    > There's no need to use both void and char pointers; converting a
    > correctly aligned pointer to and from a char pointer is guaranteed to
    > work. "Char" would be just as correct as "unsigned char" but the
    > latter is perhaps better for generic byte pointers.
    >

    Seems like I get some warnings when I get a little too frisky with
    pointer assignments and casts, and I don't use code that has warnings...let
    me see what happens...

    > Using a cast in the accumulating expression instead of an extra
    > variable and assignment might not be to everyone's taste, but reducing
    > the vertical size of a function aids readability in my opinion.
    >
    > When a loop is over a sequence of integers, a for loop is clearer than
    > a while loop.
    >

    Yeah, more straightforward to maintain and code in the first place,
    too...there is no particular logic as to why I used a "while" loop in the
    test code I posted...

    ---
    William Ernest Reid
     
    Bill Reid, May 14, 2007
    #11
  12. On Sun, 13 May 2007 20:33:11 GMT, "Bill Reid"
    <> wrote:

    >
    >Walter Roberson <-cnrc.gc.ca> wrote in message
    >news:f27kud$50$...
    >> In article <3eI1i.144346$>,
    >> Bill Reid <> wrote:
    >>
    >> You fail to include <stdio.h>, which would affect the interpretation
    >> of printf(), possibly causing garbage values to be printed out.
    >>

    >Uh, yeah, for me on this compiler, just a warning, I think. I haven't
    >actually compiled the actual code I posted, just similar stuff...


    No, it is a diagnostic. The fact that your compiler calls it a
    warning is irrelevant. The error causes undefined behavior.

    >
    >> Other than that: what is the difference between the output you
    >> see and the output you expect?

    >
    >I get exactly what I expect. Honestly, I was looking for some
    >type of criticism of the general approach for accessing structure
    >elements in add_double_numbers(), that's all.


    If you haven't compiled the code, then how do you get what you expect?

    >
    >> There are some ideas so wrong that only a very intelligent person
    >> could believe in them. -- George Orwell

    >
    >That is precisely the point, that is precisely the point. Here, let's
    >try again...what is wrong with this code?


    It suffers from attempting to implement a really poor design. You go
    through ridiculous contortions whose only apparent purpose is to avoid
    using a pointer to struct.

    A little horizontal white space would make your code a lot more
    readable.

    >
    >#include <stdio.h> /* !!!!!!!!!!!! */
    >
    >#define MAX_VALUES 64
    >
    >typedef struct {
    > unsigned value_1;
    > double value_2;
    > double value_3;
    > double value_4;
    > } VALUES;
    >
    >typedef struct {
    > unsigned num_values;
    > unsigned tot_value_1;
    > double tot_value_2;
    > double tot_value_3;
    > double tot_value_4;
    > VALUES values[MAX_VALUES];
    > } VALUES_STRUCT;
    >
    >VALUES_STRUCT values_struct=
    >{3,0,0.0,0.0,0.0,{{1,1.0,1.0,1.0},{1,1.0,1.0,1.0},{1,1.0,1.0,1.0}}};


    The use of a global struct is another unnecessary design flaw.

    >
    >double add_double_numbers
    >(void *number,unsigned num_numbers,unsigned inc_size) {


    If you change the first parameter to VALUES *struct_ptr, you can
    eliminate the third parameter ..

    > void *void_ptr=NULL;
    > char *inc_ptr=number;
    > double *double_ptr=NULL;


    and all three of these ...

    > unsigned number_num=0;
    > double total=0.0;
    >
    > while(number_num<num_numbers) {
    > void_ptr=inc_ptr;
    > double_ptr=void_ptr;


    and both of these ...

    > total+=*double_ptr;


    and change the second expression to struct_ptr->value_4

    > inc_ptr+=inc_size;


    and replace this with a simple
    struct_ptr++;

    > number_num++;
    > }


    The common idiom for this loop would be
    for (number_num = 0;
    number_num < num_numbers;
    number_num++, struct_ptr++){
    and delete the last two lines of "manual increments."

    >
    > return total;
    > }
    >
    >void add_value_4(void) {
    >
    > values_struct.tot_value_4=add_double_numbers
    > (&values_struct.values[0].value_4,values_struct.num_values,
    > sizeof(VALUES));


    The argument list would then be
    (values_struct.values, values_struct.num_values)
    >
    > printf("\nThe total is %f",values_struct.tot_value_4);


    Since your value is a double, why not use %lf and avail yourself of
    the extra precision.

    > }
    >
    >int main(void) {
    >
    > add_value_4();
    >
    > return 0;
    > }
    >
    >---



    Remove del for email
     
    Barry Schwarz, May 14, 2007
    #12
  13. In article <>,
    Barry Schwarz <> wrote:

    >It suffers from attempting to implement a really poor design. You go
    >through ridiculous contortions whose only apparent purpose is to avoid
    >using a pointer to struct.


    I think you've missed the point. It's intended to be usable with
    different structures and different members of the structures. Of
    course, a comment explaining that would be a good idea!

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
     
    Richard Tobin, May 14, 2007
    #13
  14. Bill Reid

    Chris Torek Guest

    >Richard Tobin <> wrote in message
    >news:f280o9$g5l$...
    >> I prefer my variable names; others may disagree. ("Stride" is a
    >> standard term for this sort of distance between successive elements.)


    In article <1SM1i.145726$>,
    Bill Reid <> wrote:
    >Never really heard of it...


    It is a compiler-geek term, found in "array descriptors" in languages
    that have such things (the common keywords here are "base",
    "bound(s)", "offset", and "stride"). I almost used it, but decided
    to stick with the original name, when I switched to "i" and "n".
    --
    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, May 14, 2007
    #14
  15. Bill Reid

    Ernie Wright Guest

    Chris Torek wrote:

    >> Richard Tobin wrote:
    >>
    >>> ("Stride" is a standard term for this sort of distance between
    >>> successive elements.)

    >
    > Bill Reid wrote:
    >
    >> Never really heard of it...

    >
    > It is a compiler-geek term, found in "array descriptors" in languages
    > that have such things


    It's also pretty common in computer graphics, where it denotes, for
    example, the distance in bytes between the start of two successive rows
    of an image. Because of alignment, interleaving, bitplaning, and other
    things, this distance often differs from the one that might be inferred
    from the image width and number of bits per pixel.

    - Ernie http://home.comcast.net/~erniew
     
    Ernie Wright, May 14, 2007
    #15
  16. Ernie Wright said:

    > Chris Torek wrote:
    >
    >> ["Stride"] is a compiler-geek term, found in "array descriptors"
    >> in languages that have such things

    >
    > It's also pretty common in computer graphics, where it denotes,
    > for example, the distance in bytes between the start of two
    > successive rows of an image. Because of alignment, interleaving,
    > bitplaning, and other things, this distance often differs from
    > the one that might be inferred from the image width and number
    > of bits per pixel.


    To give a slightly different example of "stride", VGA gives you eight
    (or possibly sixteen?) pages of 80x25 video memory, each of which
    occupies 2000 bytes (80 x 25 x 2), but nevertheless starts on a
    2048-byte boundary. I think this was possibly more for convenience than
    for speed; 2048-byte boundaries are easy to remember, ending as they do
    in either 0x...000 or 0x...800.

    To the terminally insane, this meant you had a whole bunch of 48-byte
    blocks where you could squirrel away stuff that wouldn't fit anywhere
    else... </blush>

    --
    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, May 14, 2007
    #16
  17. Bill Reid

    Don Bruder Guest

    In article <>,
    Richard Heathfield <> wrote:

    > Ernie Wright said:
    >
    > > Chris Torek wrote:
    > >
    > >> ["Stride"] is a compiler-geek term, found in "array descriptors"
    > >> in languages that have such things

    > >
    > > It's also pretty common in computer graphics, where it denotes,
    > > for example, the distance in bytes between the start of two
    > > successive rows of an image. Because of alignment, interleaving,
    > > bitplaning, and other things, this distance often differs from
    > > the one that might be inferred from the image width and number
    > > of bits per pixel.

    >
    > To give a slightly different example of "stride", VGA gives you eight
    > (or possibly sixteen?) pages of 80x25 video memory, each of which
    > occupies 2000 bytes (80 x 25 x 2), but nevertheless starts on a
    > 2048-byte boundary. I think this was possibly more for convenience than
    > for speed; 2048-byte boundaries are easy to remember, ending as they do
    > in either 0x...000 or 0x...800.
    >
    > To the terminally insane, this meant you had a whole bunch of 48-byte
    > blocks where you could squirrel away stuff that wouldn't fit anywhere
    > else... </blush>


    Why does this remind me of the old Apple II's "screen holes"? :)

    --
    Don Bruder - - If your "From:" address isn't on my whitelist,
    or the subject of the message doesn't contain the exact text "PopperAndShadow"
    somewhere, any message sent to this address will go in the garbage without my
    ever knowing it arrived. Sorry... <http://www.sonic.net/~dakidd> for more info
     
    Don Bruder, May 14, 2007
    #17
  18. Bill Reid

    Bill Reid Guest

    Chris Torek <> wrote in message
    news:...
    > In article <bCK1i.144938$>
    > Bill Reid <> wrote:


    > >I get exactly what I expect. Honestly, I was looking for some
    > >type of criticism of the general approach for accessing structure
    > >elements in add_double_numbers(), that's all.

    >
    > Oh ... in that case, as far as I can tell, the code is valid. It
    > does seem "slightly dangerous" (in the sense that it would be easy
    > for a caller to provide improper arguments, and then have everything
    > go kaboom). Also, while we tend to discourage casts in comp.lang.c,
    > I would probably go ahead and use them here, and make a few other
    > minor changes:
    >
    > /*
    > * Iterate over some kind of array, which may be an array of structures
    > * or array of arrays, in which there is at least one "double" element.
    > * Add up the n "double" elements that are spaced apart by
    > * "inc_size" bytes, given a pointer to the first such "double".
    > */
    > double add_double_numbers(double *first, size_t n, size_t inc_size) {
    > unsigned char *p; /* will point to our various "double"s */
    > double total = 0.0;
    > size_t i;
    >
    > p = (unsigned char *)first;
    > for (i = 0; i < n; i++) {
    > total += *(double *)p;
    > p += inc_size;
    > }
    > return total;
    > }
    >

    OK, I've tested this and it is a perfect "drop-in" fit for any of my
    fundamental libraries that implement this type of structure element
    access. It's got to be a little quicker because it eliminates the unneeded
    pointer assignments (considering these libraries perform at least several
    hundred billion loops a day, that's got to be worth a few seconds), and
    should be more "type-safe" as well for ongoing development.

    So thanks again because that's EXACTLY what I was looking for;
    my original design was just the result of my general inability to handle
    pointers very adroitly...

    ---
    William Ernest Reid
     
    Bill Reid, May 14, 2007
    #18
  19. Bill Reid

    Bill Reid Guest

    Richard Tobin <> wrote in message
    news:f280o9$g5l$...
    > In article <3eI1i.144346$>,
    > Bill Reid <> wrote:
    >
    > To avoid replicating the fields here, you could do
    >
    > typedef struct {
    > unsigned num_values;
    > VALUES total[MAX_VALUES];
    > VALUES values[MAX_VALUES];
    > } VALUES_STRUCT;
    >
    > and refer to v.total.value1 instead of v.tot_value_1, etc.
    >

    Yeah, for the purposes of this "toy" code, but of course I really
    WASN'T trying to add 1.0+1.0+1.0, despite what some people
    seem to think! An actual structure I use might consist of several
    dozen "results" or "descriptive" variables along with pointers to
    several malloc'd arrays of 50-100 thousand structures containing
    related values of floats, doubles, long doubles, ints...
    >
    > I would prefer something like:
    >
    > double add_double_numbers(double *base, size_t count, size_t stride)
    > {
    > unsigned char *byte_ptr = (unsigned char *)base;
    > unsigned i;
    > double total=0.0;
    >
    > for(i=0; i<count; i++)
    > {
    > total += *(double *)byte_ptr;
    > byte_ptr += stride;
    > }
    >
    > return total;
    > }
    >
    > Since the function only works for doubles, you gain nothing by making
    > the argument void *; use double * to emphasise its meaning.
    >

    Yup, this is almost identical to what Chris Torek came up with,
    works like a champ. Thanks.

    > size_t is the right type for object counts and sizes (cf calloc()).
    >

    Yes, "technically", which of course what this is all about...

    > I prefer my variable names; others may disagree.


    I tend to prefer nice big preferably unabbreviated English words that
    I can understand immediately, but that's not really a "C" convention, now
    is it?
    >
    > There's no need to use both void and char pointers; converting a
    > correctly aligned pointer to and from a char pointer is guaranteed to
    > work.


    Yeah, this was a confusion on my part...I didn't really know that,
    at least in a useful sense...

    ---
    William Ernest Reid
     
    Bill Reid, May 14, 2007
    #19
  20. Bill Reid

    Bill Reid Guest

    Barry Schwarz <> wrote in message
    news:eek:...
    > On Sun, 13 May 2007 20:33:11 GMT, "Bill Reid"
    > <> wrote:
    > >Walter Roberson <-cnrc.gc.ca> wrote in message
    > >news:f27kud$50$...
    > >> In article

    <3eI1i.144346$>,
    > >> Bill Reid <> wrote:
    > >>
    > >> You fail to include <stdio.h>, which would affect the interpretation
    > >> of printf(), possibly causing garbage values to be printed out.
    > >>

    > >Uh, yeah, for me on this compiler, just a warning, I think. I haven't
    > >actually compiled the actual code I posted, just similar stuff...

    >
    > No, it is a diagnostic. The fact that your compiler calls it a
    > warning is irrelevant. The error causes undefined behavior.
    >
    > >> Other than that: what is the difference between the output you
    > >> see and the output you expect?

    > >
    > >I get exactly what I expect. Honestly, I was looking for some
    > >type of criticism of the general approach for accessing structure
    > >elements in add_double_numbers(), that's all.

    >
    > If you haven't compiled the code, then how do you get what you expect?
    >

    Ummmm, let's think about this...maybe because I actually compiled
    and linked two separate "translation units" with "extern" declarations
    and typedefs in a what's called a "header file"? Maybe I just cut and
    pasted that code into what appears to be a single source code file,
    and just forgot to paste in the include stdio.h define? Naaahhhh,
    never happen...
    > >
    > >> There are some ideas so wrong that only a very intelligent person
    > >> could believe in them. -- George Orwell

    > >
    > >That is precisely the point, that is precisely the point. Here, let's
    > >try again...what is wrong with this code?

    >
    > It suffers from attempting to implement a really poor design. You go
    > through ridiculous contortions whose only apparent purpose is to avoid
    > using a pointer to struct.
    >

    To repeat myself:

    "That is precisely the point, that is precisely the point."

    Hey, why not take it a step further; I'm actually going through the
    ridiculous contortions to avoid using a pointer to an ARRAY. After
    all, why couldn't I just declare four separate arrays, with four
    separate variables for the number of elements in the arrays?
    What the hell is the matter with me, anyway?

    > A little horizontal white space would make your code a lot more
    > readable.


    Another egregious personality flaw, perhaps requiring "professional"
    help...
    > >
    > >VALUES_STRUCT values_struct=
    > >{3,0,0.0,0.0,0.0,{{1,1.0,1.0,1.0},{1,1.0,1.0,1.0},{1,1.0,1.0,1.0}}};

    >
    > The use of a global struct is another unnecessary design flaw.
    >

    Well, you didn't actually make me laugh here, but you did make
    me smile...
    > >
    > >double add_double_numbers
    > >(void *number,unsigned num_numbers,unsigned inc_size) {

    >
    > If you change the first parameter to VALUES *struct_ptr, you can
    > eliminate the third parameter ..
    >

    Actually, thinking about it even more, I know realize that I could
    have just done it like this:

    double number_4_1=1.0;
    double number_4_2=1.0;
    double number_4_3=1.0;

    double add_double_numbers_4(void) {
    return (number_4_1+number_4_2+number_4_3);
    }

    OK, call off the hunt, we have a winner!!!

    > > void *void_ptr=NULL;
    > > char *inc_ptr=number;
    > > double *double_ptr=NULL;

    >
    > and all three of these ...
    >

    Yeah, I've got you beat, but you helped!

    > > unsigned number_num=0;
    > > double total=0.0;
    > >
    > > while(number_num<num_numbers) {
    > > void_ptr=inc_ptr;
    > > double_ptr=void_ptr;

    >
    > and both of these ...
    >

    Mine's much better, but again, you helped!

    > > total+=*double_ptr;

    >
    > and change the second expression to struct_ptr->value_4
    >
    > > inc_ptr+=inc_size;

    >
    > and replace this with a simple
    > struct_ptr++;
    >
    > > number_num++;
    > > }

    >

    Well, now I FINALLY know how to increment through an array of
    structs...
    > >
    > > printf("\nThe total is %f",values_struct.tot_value_4);

    >
    > Since your value is a double, why not use %lf and avail yourself of
    > the extra precision.
    >

    Oh, I guess I just thought it was overkill for adding 1.0+1.0+1.0...but
    you never know, tomorrow, I might try to add 2.0+2.0+2.0!!!

    ---
    William Ernest Reid
     
    Bill Reid, May 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. walala
    Replies:
    3
    Views:
    2,206
    Ralf Hildebrandt
    Sep 10, 2003
  2. willem oosthuizen

    What is wrong with the following code?

    willem oosthuizen, Oct 10, 2003, in forum: VHDL
    Replies:
    9
    Views:
    1,283
  3. Matthew
    Replies:
    7
    Views:
    681
    Priscilla Walmsley
    Jan 7, 2005
  4. David. E. Goble
    Replies:
    9
    Views:
    484
    David. E. Goble
    Feb 2, 2005
  5. kiran
    Replies:
    12
    Views:
    1,133
    Scott Sauyet
    Dec 7, 2011
Loading...

Share This Page