Newbie needs help with pointers/memory allocation

Discussion in 'C Programming' started by Me Alone, Aug 17, 2006.

  1. Me Alone

    Me Alone Guest

    Hello list:

    I am working on a C assignment. I am to declare a (pointer to pointer
    to int), allocate memory for pointer and data, and print some output.

    Problem (I think): The memory addresses printed don't look right. Would
    any one be so kind to take a look at my code and explain why are the
    addresses for the lists printed in "less than optimal" sequence?

    Thanks in advance,
    Ron

    ##########################################

    #include <stdio.h>

    #define T1 2
    #define T2 5

    main()
    {
    int i, j, **ptr;

    if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)
    {
    error("Error encountered, will exit now.");
    exit(0);
    }

    if ((*ptr = (int*)malloc(T1 * T2 * sizeof(int))) == NULL)
    {
    error("Error encountered, will exit now.");
    exit(0);
    }

    for(i=0;i<T1;i++)
    {
    printf("\nData in table (%d).\n", i);
    printf("**ptr addr\t*ptr addr\tvalue\n");
    printf("=====================================\n");
    for(j=0;j<T2;j++)
    {
    if(i > 0)
    {
    *(ptr+i+j) = j + T2;
    printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, (ptr+i+j));
    } else {
    *(ptr+i+j) = j;
    printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, *(ptr+i+j));
    }
    }
    }
    printf("\n");
    }


    // Output of program
    Data in table (0).
    **ptr addr *ptr addr value
    =====================================
    BFF06C84 BFF06C84 0
    BFF06C84 BFF06C88 1
    BFF06C84 BFF06C8C 2
    BFF06C84 BFF06C90 3
    BFF06C84 BFF06C94 4

    Data in table (1).
    **ptr addr *ptr addr value
    =====================================
    BFF06C88 BFF06C88 5
    BFF06C88 BFF06C8C 6
    BFF06C88 BFF06C90 7
    BFF06C88 BFF06C94 8
    BFF06C88 BFF06C98 9
     
    Me Alone, Aug 17, 2006
    #1
    1. Advertising

  2. Me Alone posted:

    > Hello list:
    >
    > I am working on a C assignment. I am to declare a (pointer to pointer
    > to int), allocate memory for pointer and data, and print some output.



    The following might get you going:

    #include <stdio.h>

    #define AL(arr) (sizeof(arr)/sizeof*(arr))

    int main(void)
    {
    int const iarr[] = {0,1,2,3,4,5,6,7,8,9};

    int const *const parr[] = {iarr,iarr+1,iarr+2,iarr+3,iarr+4,
    iarr+5,iarr+6,iarr+7,iarr+8,iarr+9};

    int const *const *p = parr;

    int const *const *const p_over = parr + AL(parr);

    do
    {
    printf("%d",**p++);
    } while(p != p_over);

    return 0;
    }


    > #include <stdio.h>



    You'l also want:

    #include <stdlib.h>


    > #define T1 2
    > #define T2 5
    >
    > main()



    Change that to:

    int main(void)


    > {
    > int i, j, **ptr;
    >
    > if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)



    Don't cast the return value of "malloc" -- it makes you look like a novice.

    Try this:

    if( !(ptr = malloc(T1 * sizeof*ptr)) )


    > {
    > error("Error encountered, will exit now.");
    > exit(0);
    > }
    >
    > if ((*ptr = (int*)malloc(T1 * T2 * sizeof(int))) == NULL)



    Again, don't cast the return value of malloc.

    if( !(*ptr = malloc(T1 * T2 * sizeof**ptr)) )

    Sorry, I'd examine the rest of your code, but my brain's taken enough
    screen-staring for today.

    --

    Frederick Gotham
     
    Frederick Gotham, Aug 17, 2006
    #2
    1. Advertising

  3. On Wed, 16 Aug 2006 18:06:53 -0500, Me Alone <> wrote:

    >Hello list:
    >
    >I am working on a C assignment. I am to declare a (pointer to pointer
    >to int), allocate memory for pointer and data, and print some output.
    >
    >Problem (I think): The memory addresses printed don't look right. Would
    >any one be so kind to take a look at my code and explain why are the
    >addresses for the lists printed in "less than optimal" sequence?
    >
    >Thanks in advance,
    >Ron
    >
    >##########################################
    >
    >#include <stdio.h>


    You need stdlib.h for malloc.

    >
    >#define T1 2
    >#define T2 5
    >
    >main()
    >{
    > int i, j, **ptr;
    >
    > if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)


    Don't cast the return from malloc. It never helps but can cause the
    compiler to suppress a diagnostic you would really like to see. And
    your code does have the error which the compiler would catch.

    ptr points to an uninitialized array of 2 int*.

    > {
    > error("Error encountered, will exit now.");


    There is no error function defined.

    > exit(0);
    > }
    >
    > if ((*ptr = (int*)malloc(T1 * T2 * sizeof(int))) == NULL)


    *ptr (which is the same as ptr[0]) points to an array of 10 int.

    > {
    > error("Error encountered, will exit now.");
    > exit(0);
    > }
    >
    > for(i=0;i<T1;i++)
    > {
    > printf("\nData in table (%d).\n", i);
    > printf("**ptr addr\t*ptr addr\tvalue\n");
    > printf("=====================================\n");
    > for(j=0;j<T2;j++)
    > {
    > if(i > 0)
    > {
    > *(ptr+i+j) = j + T2;
    > printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, (ptr+i+j));


    & has higher precedence than +. This evaluates as (&ptr)+i. Since
    ptr has type int**, &ptr has type int***. So does the sum. I'm
    pretty sure this is not what you wanted. When i+j > 1, the expression
    &ptr+i+j is not a valid value.

    If you want to print addresses using printf, you should use %p and
    cast the value to void*.

    > } else {
    > *(ptr+i+j) = j;


    *(ptr+i+j) is the same as ptr[i+j]. Since ptr is an int**, ptr[i+j]
    is an int*. j is an int. You cannot assign an int to an int* without
    a cast (and in this program you don't even want to). Did your
    compiler not generate a diagnostic here? If not, you need to up the
    warning level so it does.

    > printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, *(ptr+i+j));
    > }
    > }
    > }
    > printf("\n");
    >}
    >
    >
    >// Output of program


    Why did you execute a program that does not compile cleanly?

    >Data in table (0).
    >**ptr addr *ptr addr value
    >=====================================
    >BFF06C84 BFF06C84 0
    >BFF06C84 BFF06C88 1
    >BFF06C84 BFF06C8C 2
    >BFF06C84 BFF06C90 3
    >BFF06C84 BFF06C94 4
    >
    >Data in table (1).
    >**ptr addr *ptr addr value
    >=====================================
    >BFF06C88 BFF06C88 5
    >BFF06C88 BFF06C8C 6
    >BFF06C88 BFF06C90 7
    >BFF06C88 BFF06C94 8
    >BFF06C88 BFF06C98 9



    Remove del for email
     
    Barry Schwarz, Aug 17, 2006
    #3
  4. On 2006-08-16, Me Alone <> wrote:
    > Hello list:
    >
    > I am working on a C assignment. I am to declare a (pointer to pointer
    > to int), allocate memory for pointer and data, and print some output.
    >
    > Problem (I think): The memory addresses printed don't look right. Would
    > any one be so kind to take a look at my code and explain why are the
    > addresses for the lists printed in "less than optimal" sequence?
    >
    > Thanks in advance,
    > Ron
    >
    > ##########################################
    >
    > #include <stdio.h>
    >
    > #define T1 2
    > #define T2 5
    >


    Magic numbers are almost better than these unmeaningful macros. You
    should have better names.

    > main()


    int main (void) is the preferred style, and one that will work with C99.

    > {
    > int i, j, **ptr;


    Don't declare pointers and non-pointers on the same line; they're
    different types. This is legal, but poor style.

    >
    > if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)


    1) There's no reason to have an assignment in an if statement; move it
    to the line above for more readability. (This isn't too important for
    such a short line.)
    2) Don't cast the result of malloc(). It hides the fact that you didn't
    include <stdlib.h> and causes undefined behavior.
    3) Don't use sizeof on a type. It's almost never what you want to do.

    ptr = malloc (T1 * sizeof *ptr);
    if (ptr == NULL)
    ...

    > {
    > error("Error encountered, will exit now.");


    1) error() is not a standard function. We at clc have no idea what it does.
    2) This error message is thoroughly useless; describe the problem.

    > exit(0);


    exit (EXIT_FAILURE); would be better.

    > }
    >
    > if ((*ptr = (int*)malloc(T1 * T2 * sizeof(int))) == NULL)
    > {
    > error("Error encountered, will exit now.");
    > exit(0);
    > }
    >


    Ditto.

    > for(i=0;i<T1;i++)
    > {
    > printf("\nData in table (%d).\n", i);
    > printf("**ptr addr\t*ptr addr\tvalue\n");
    > printf("=====================================\n");
    > for(j=0;j<T2;j++)
    > {
    > if(i > 0)
    > {
    > *(ptr+i+j) = j + T2;
    > printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, (ptr+i+j));
    > } else {
    > *(ptr+i+j) = j;
    > printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, *(ptr+i+j));
    > }
    > }
    > }
    > printf("\n");
    > }
    >


    To print the value of a pointer, use %p and cast to void*:
    printf ("Value of my pointer: %p\n", (void *) ptr);

    >
    > // Output of program

    [Demons extracted from nose and are forced to ride a purple donkey.]
    [Or maybe not. Anything can happen with Undefined Behavior.]

    --
    Andrew Poelstra <http://www.wpsoftware.net/projects>
    To reach me by email, use `apoelstra' at the above domain.
    "Do BOTH ends of the cable need to be plugged in?" -Anon.
     
    Andrew Poelstra, Aug 17, 2006
    #4
  5. On Wed, 16 Aug 2006 23:06:53 UTC, Me Alone <> wrote:

    > Hello list:
    >
    > I am working on a C assignment. I am to declare a (pointer to pointer
    > to int), allocate memory for pointer and data, and print some output.
    >
    > Problem (I think): The memory addresses printed don't look right. Would
    > any one be so kind to take a look at my code and explain why are the
    > addresses for the lists printed in "less than optimal" sequence?
    >
    > Thanks in advance,
    > Ron
    >
    > ##########################################
    >
    > #include <stdio.h>
    >
    > #define T1 2
    > #define T2 5
    >
    > main()


    Has to be
    int main(void)
    since more than 16 years now.

    > {
    > int i, j, **ptr;
    >
    > if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)


    Casting the result of malloc ends up in undefined behaviuor in special
    when one forgets to include stdlib.h. And even when you includes
    stdlib.h it is a faiture to cast.

    In C there is already never a need to cast a pointer to void. Only a
    dumbass who knows not what he does is able to cast a pointer to void
    to anything else or cast a pointer to any datatype to a pointer to
    void.

    A programmer who knows what he is doing will avoid any cast only
    because the compiler gives a diagnostic as he knows that the
    diagnostic shows an error he'd made and the error is NOT becaue he'd
    forgotten to cast.

    > {
    > error("Error encountered, will exit now.");
    > exit(0);
    > }
    >
    > if ((*ptr = (int*)malloc(T1 * T2 * sizeof(int))) == NULL)


    The same as above.

    > {
    > error("Error encountered, will exit now.");
    > exit(0);
    > }
    >
    > for(i=0;i<T1;i++)
    > {
    > printf("\nData in table (%d).\n", i);
    > printf("**ptr addr\t*ptr addr\tvalue\n");
    > printf("=====================================\n");
    > for(j=0;j<T2;j++)
    > {
    > if(i > 0)
    > {
    > *(ptr+i+j) = j + T2;
    > printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, (ptr+i+j));
    > } else {
    > *(ptr+i+j) = j;
    > printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, *(ptr+i+j));
    > }
    > }
    > }
    > printf("\n");
    > }
    >
    >
    > // Output of program
    > Data in table (0).
    > **ptr addr *ptr addr value
    > =====================================
    > BFF06C84 BFF06C84 0
    > BFF06C84 BFF06C88 1
    > BFF06C84 BFF06C8C 2
    > BFF06C84 BFF06C90 3
    > BFF06C84 BFF06C94 4
    >
    > Data in table (1).
    > **ptr addr *ptr addr value
    > =====================================
    > BFF06C88 BFF06C88 5
    > BFF06C88 BFF06C8C 6
    > BFF06C88 BFF06C90 7
    > BFF06C88 BFF06C94 8
    > BFF06C88 BFF06C98 9
    >


    Repair your program by removing the casts and the real cause the
    compiler complains.

    --
    Tschau/Bye
    Herbert

    Visit http://www.ecomstation.de the home of german eComStation
    eComStation 1.2 Deutsch ist da!
     
    Herbert Rosenau, Aug 17, 2006
    #5
  6. Herbert Rosenau wrote:
    > On Wed, 16 Aug 2006 23:06:53 UTC, Me Alone <> wrote:
    >
    >> Hello list:
    >>
    >> I am working on a C assignment. I am to declare a (pointer to pointer
    >> to int), allocate memory for pointer and data, and print some output.
    >>
    >> Problem (I think): The memory addresses printed don't look right. Would
    >> any one be so kind to take a look at my code and explain why are the
    >> addresses for the lists printed in "less than optimal" sequence?
    >>
    >> Thanks in advance,
    >> Ron
    >>
    >> ##########################################
    >>
    >> #include <stdio.h>
    >>
    >> #define T1 2
    >> #define T2 5
    >>
    >> main()

    >
    > Has to be
    > int main(void)
    > since more than 16 years now.


    In C89, main() is valid. It declares main() as returning int and taking no
    parameters. The lack of a prototype only affects how and when diagnostics
    are generated for invalid recursive calls to main(), and the lack of an
    explicit return type is at worst bad style.

    >> {
    >> int i, j, **ptr;
    >>
    >> if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)

    >
    > Casting the result of malloc ends up in undefined behaviuor in special
    > when one forgets to include stdlib.h.


    Thanks for at least clarifying this now, but there's still one minor thing.
    The behaviour is well-defined if malloc() is called with a proper
    declaration in scope. This can happen with or without including <stdlib.h>:

    #include <stddef.h>

    extern void *malloc(size_t);
    extern void free(void *);

    int main(void) {
    free(malloc(1)); /* no undefined behaviour */
    free((char *) malloc(1)); /* still no undefined behaviour */
    return 0;
    }

    > And even when you includes
    > stdlib.h it is a faiture to cast.


    Rather, it's considered bad style in most cases.

    > In C there is already never a need to cast a pointer to void. Only a
    > dumbass who knows not what he does is able to cast a pointer to void
    > to anything else or cast a pointer to any datatype to a pointer to
    > void.


    You never answered how you would store a pointer value in an object of type
    intptr_t or uintptr_t. Or do only dumbasses do that? Do real programmers
    use intptr_t to store currency values, perhaps?

    > A programmer who knows what he is doing will avoid any cast only
    > because the compiler gives a diagnostic as he knows that the
    > diagnostic shows an error he'd made and the error is NOT becaue he'd
    > forgotten to cast.


    Here you go again with your overly broad claims. "Any" cast? Do you want to
    clarify that?
     
    Harald van =?UTF-8?B?RMSzaw==?=, Aug 17, 2006
    #6
  7. "Herbert Rosenau" <> writes:
    > On Wed, 16 Aug 2006 23:06:53 UTC, Me Alone <> wrote:
    >> I am working on a C assignment. I am to declare a (pointer to pointer
    >> to int), allocate memory for pointer and data, and print some output.
    >>
    >> Problem (I think): The memory addresses printed don't look right. Would
    >> any one be so kind to take a look at my code and explain why are the
    >> addresses for the lists printed in "less than optimal" sequence?
    >>
    >> Thanks in advance,
    >> Ron
    >>
    >> ##########################################
    >>
    >> #include <stdio.h>
    >>
    >> #define T1 2
    >> #define T2 5
    >>
    >> main()

    >
    > Has to be
    > int main(void)
    > since more than 16 years now.


    That's incorrect. In C90, "main()" is perfectly legal, and if I
    recall correctly you'll find multiple instances of it in examples in
    K&R2. C99 removed implicit int from the language, making "main()" a
    constraint violation, but few compilers enforce this unless they're
    specifically invoked in a strict C99-conforming mode.

    "int main(void)" is better than "main()", and it has been since the
    ANSI standard was introduced in 1989, but there's no need to overstate
    the case.

    >> {
    >> int i, j, **ptr;
    >>
    >> if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)

    >
    > Casting the result of malloc ends up in undefined behaviuor in special
    > when one forgets to include stdlib.h. And even when you includes
    > stdlib.h it is a faiture to cast.


    Didn't we just go over this?

    No, casting the result of malloc() does not invoke undefined behavior.
    If there's no visible prototype for malloc() (the way to get one is
    "#include <stdlib.h>"), then just *calling* malloc() invokes undefined
    behavior, regardless of what you do with the result.

    See the FAQ for more information.

    > In C there is already never a need to cast a pointer to void. Only a
    > dumbass who knows not what he does is able to cast a pointer to void
    > to anything else or cast a pointer to any datatype to a pointer to
    > void.


    I haven't found that calling people "dumbasses" is a particularly
    effective teaching tool. Does it work for you?

    You're absolutely correct that casting the result of malloc() is not
    necessary and should be avoided. Please don't give misleading advice
    about *why* it's a bad idea.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Aug 17, 2006
    #7
  8. Harald van Dijk <> writes:
    > Herbert Rosenau wrote:

    [...]
    >> A programmer who knows what he is doing will avoid any cast only
    >> because the compiler gives a diagnostic as he knows that the
    >> diagnostic shows an error he'd made and the error is NOT becaue he'd
    >> forgotten to cast.

    >
    > Here you go again with your overly broad claims. "Any" cast? Do you want to
    > clarify that?


    I think what he meant here is that any cast that's added merely for
    the purpose of shutting up a compiler diagnostic is a bad idea.

    There are cases where casts are appropriate. There are far fewer such
    cases than many C programmers seem to believe.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Aug 17, 2006
    #8
  9. Keith Thompson wrote:

    > Harald van Dijk <> writes:
    >> Herbert Rosenau wrote:

    > [...]
    >>> A programmer who knows what he is doing will avoid any cast only
    >>> because the compiler gives a diagnostic as he knows that the
    >>> diagnostic shows an error he'd made and the error is NOT becaue he'd
    >>> forgotten to cast.

    >>
    >> Here you go again with your overly broad claims. "Any" cast? Do you want
    >> to clarify that?

    >
    > I think what he meant here is that any cast that's added merely for
    > the purpose of shutting up a compiler diagnostic is a bad idea.


    Which is why I asked for clarification. My compiler generates a diagnostic
    for

    long long i = 1 << 40;

    Adding a cast to shut it up:

    long long i = (long long) 1 << 40;

    is one way of fixing the code. (A suffix is another, but that is not an
    option when using a variable.)

    > There are cases where casts are appropriate. There are far fewer such
    > cases than many C programmers seem to believe.


    Probably so.
     
    Harald van =?UTF-8?B?RMSzaw==?=, Aug 18, 2006
    #9
  10. On Thu, 17 Aug 2006 22:42:36 UTC, Keith Thompson <>
    wrote:

    > >>
    > >> main()

    > >
    > > Has to be
    > > int main(void)
    > > since more than 16 years now.

    >
    > That's incorrect. In C90, "main()" is perfectly legal, and if I
    > recall correctly you'll find multiple instances of it in examples in
    > K&R2. C99 removed implicit int from the language, making "main()" a
    > constraint violation, but few compilers enforce this unless they're
    > specifically invoked in a strict C99-conforming mode.


    It is deprecated anyway. Using that will hinder you to to to ANSI99
    always. 16 years of standard should be enough to accept that.

    > "int main(void)" is better than "main()", and it has been since the
    > ANSI standard was introduced in 1989, but there's no need to overstate
    > the case.
    >
    > >> {
    > >> int i, j, **ptr;
    > >>
    > >> if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)

    > >
    > > Casting the result of malloc ends up in undefined behaviuor in special
    > > when one forgets to include stdlib.h. And even when you includes
    > > stdlib.h it is a faiture to cast.

    >
    > Didn't we just go over this?
    >
    > No, casting the result of malloc() does not invoke undefined behavior.
    > If there's no visible prototype for malloc() (the way to get one is
    > "#include <stdlib.h>"), then just *calling* malloc() invokes undefined
    > behavior, regardless of what you do with the result.


    I've seen idiots removing #include <stdlib.h> and then failing into
    undefined behavior on malloc().

    Have you never learned to program failsave?

    > See the FAQ for more information.
    >
    > > In C there is already never a need to cast a pointer to void. Only a
    > > dumbass who knows not what he does is able to cast a pointer to void
    > > to anything else or cast a pointer to any datatype to a pointer to
    > > void.

    >
    > I haven't found that calling people "dumbasses" is a particularly
    > effective teaching tool. Does it work for you?
    >
    > You're absolutely correct that casting the result of malloc() is not
    > necessary and should be avoided. Please don't give misleading advice
    > about *why* it's a bad idea.
    >

    It IS a bad idea because
    - undiefined behavior occures when stdlib is not included.
    Having it yet included does not mean that somebody will remove
    that sometimes later. Not anybody knows that already as
    this group shows nearly dayly.
    - undefined behavior is guaranteed because the standard dos not
    tell that
    - int is always the same size as void*
    - the environemt uses even the same location to return int
    and pointer values as the standard does allows that.

    --
    Tschau/Bye
    Herbert

    Visit http://www.ecomstation.de the home of german eComStation
    eComStation 1.2 Deutsch ist da!
     
    Herbert Rosenau, Aug 18, 2006
    #10
  11. "Herbert Rosenau" <> writes:
    > On Thu, 17 Aug 2006 22:42:36 UTC, Keith Thompson <>
    > wrote:
    >> >>
    >> >> main()
    >> >
    >> > Has to be
    >> > int main(void)
    >> > since more than 16 years now.

    >>
    >> That's incorrect. In C90, "main()" is perfectly legal, and if I
    >> recall correctly you'll find multiple instances of it in examples in
    >> K&R2. C99 removed implicit int from the language, making "main()" a
    >> constraint violation, but few compilers enforce this unless they're
    >> specifically invoked in a strict C99-conforming mode.

    >
    > It is deprecated anyway. Using that will hinder you to to to ANSI99
    > always. 16 years of standard should be enough to accept that.


    I think you mean ANSI89 (also known as C89 or C90), not ANSI99.

    Strictly speaking, I don't think implicit int was ever *formally*
    deprecated. It was perfectly legal in C90, with (as far as I can
    tell) no hint in the standard itself that it should be avoided, then
    banned outright in C99. (My copy of the C90 standard is difficult to
    search, so I might have missed something; if so, I'm sure someone will
    post a citation.)

    But as I said, and as you quoted (but you snipped the attribution
    line; please don't do that):

    >> "int main(void)" is better than "main()", and it has been since the
    >> ANSI standard was introduced in 1989, but there's no need to overstate
    >> the case.


    I am not arguing, and I have never argued, that writing "main()"
    rather than "int main(void)" is a good idea. I am making a very
    narrow and specific point: your statement that it "Has to be
    int main(void) since more than 16 years now" was incorrect.
    It certainly *should* be but it doesn't *have* to be.

    I'm trying to forestall claims of the form, "Well, my compiler
    accepted it, so it must be ok."

    >> >> {
    >> >> int i, j, **ptr;
    >> >>
    >> >> if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)
    >> >
    >> > Casting the result of malloc ends up in undefined behaviuor in special
    >> > when one forgets to include stdlib.h. And even when you includes
    >> > stdlib.h it is a faiture to cast.

    >>
    >> Didn't we just go over this?
    >>
    >> No, casting the result of malloc() does not invoke undefined behavior.
    >> If there's no visible prototype for malloc() (the way to get one is
    >> "#include <stdlib.h>"), then just *calling* malloc() invokes undefined
    >> behavior, regardless of what you do with the result.

    >
    > I've seen idiots removing #include <stdlib.h> and then failing into
    > undefined behavior on malloc().
    >
    > Have you never learned to program failsave?


    What are you talking about? Have I ever said or implied that casting
    the result of malloc() is a good idea?

    I agree with you that casting the result of malloc() is almost always
    a bad idea. (I added the word "almost" because there are rare
    exceptions; they can be counted on the fingers of P.J. Plauger's left
    hand.)

    >> See the FAQ for more information.
    >>
    >> > In C there is already never a need to cast a pointer to void. Only a
    >> > dumbass who knows not what he does is able to cast a pointer to void
    >> > to anything else or cast a pointer to any datatype to a pointer to
    >> > void.

    >>
    >> I haven't found that calling people "dumbasses" is a particularly
    >> effective teaching tool. Does it work for you?
    >>
    >> You're absolutely correct that casting the result of malloc() is not
    >> necessary and should be avoided. Please don't give misleading advice
    >> about *why* it's a bad idea.
    >>

    > It IS a bad idea because
    > - undiefined behavior occures when stdlib is not included.
    > Having it yet included does not mean that somebody will remove
    > that sometimes later. Not anybody knows that already as
    > this group shows nearly dayly.
    > - undefined behavior is guaranteed because the standard dos not
    > tell that
    > - int is always the same size as void*
    > - the environemt uses even the same location to return int
    > and pointer values as the standard does allows that.


    Yes, I know all that, and you should know that I know it.

    Again, I was making a very narrow and specific point. Casting the
    result of malloc() is a bad idea, but the cast itself *does not*
    invoke undefined behavior.

    Let me give you an example:

    #include <stdlib.h>
    int main(void)
    {
    int *ptr = (int*)malloc(sizeof *ptr);
    if (ptr != NULL) {
    *ptr = 42;
    }
    free(ptr);
    return 0;
    }

    Let's ignore the fact that *ptr is assigned but never used.

    This program exhibits bad style. The cast is entirely unnecessary,
    and it should not be there. I would never write such a thing myself
    except as a demonstration of bad style (or if, for some unlikely
    reason, I had a real need to compile the code as either C or C++).

    But the program is also entirely valid. It does not invoke undefined
    behavior, and in fact it is strictly conforming.

    I agree with your conclusion (don't cast the result of malloc()), but
    by making incorrect statements about it you weaken your argument.

    Now do you understand?

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Aug 18, 2006
    #11
  12. Me Alone

    Flash Gordon Guest

    Harald van Dijk wrote:
    > Keith Thompson wrote:
    >
    >> Harald van Dijk <> writes:
    >>> Herbert Rosenau wrote:

    >> [...]
    >>>> A programmer who knows what he is doing will avoid any cast only
    >>>> because the compiler gives a diagnostic as he knows that the
    >>>> diagnostic shows an error he'd made and the error is NOT becaue he'd
    >>>> forgotten to cast.
    >>> Here you go again with your overly broad claims. "Any" cast? Do you want
    >>> to clarify that?

    >> I think what he meant here is that any cast that's added merely for
    >> the purpose of shutting up a compiler diagnostic is a bad idea.

    >
    > Which is why I asked for clarification. My compiler generates a diagnostic
    > for
    >
    > long long i = 1 << 40;


    Here your compiler is not *required* to produce a diagnostic, but the
    compiler writer(s) has chosen to be helpful. The numeric constant 1 fits
    in to an int so it has type int. If you try to shift by more bits than
    are in the type you are shifting (and very few systems have a 40 bit or
    larger int type) then the behaviour is undefined and *anything* is
    allowed to happen.

    > Adding a cast to shut it up:
    >
    > long long i = (long long) 1 << 40;
    >
    > is one way of fixing the code. (A suffix is another, but that is not an
    > option when using a variable.)


    Adding the cast to shut the compiler up is wrong. Adding the cast
    because it actually fixes the real problem by converting 1 to a large
    enough type to support a 40 bit shift (or, as you suggest, a variable of
    type int where you cannot use a suffix) is the right thing to do.

    Of course, looking just at the code one cannot in this case see if you
    added the cast for the right reason or the wrong reason. However, this
    is one of those rare instances where the cast is a correct solution.

    >> There are cases where casts are appropriate. There are far fewer such
    >> cases than many C programmers seem to believe.

    >
    > Probably so.


    The experience of this group (and my own personal experience) support
    Keith's assertion.
    --
    Flash Gordon
    Still sigless on this computer.
     
    Flash Gordon, Aug 19, 2006
    #12
  13. On Thu, 17 Aug 2006 22:42:36 GMT, Keith Thompson <>
    wrote:

    > "Herbert Rosenau" <> writes:


    > > Has to be
    > > int main(void)
    > > since more than 16 years now.

    >
    > That's incorrect. In C90, "main()" is perfectly legal, and if I
    > recall correctly you'll find multiple instances of it in examples in
    > K&R2. C99 removed implicit int from the language, making "main()" a
    > constraint violation, but few compilers enforce this unless they're
    > specifically invoked in a strict C99-conforming mode.
    >

    <pedantic=super> syntax error not cv. As part of the deletion of
    implicit int, C99 made (nonempty) declaration-specifiers mandatory in
    a function-definition where C89 had them optional. They were already
    mandatory in a syntactic 'declaration' which covers everything else,
    but not required to contain a type specifier (i.e. could be just
    storage class and/or qualifiers).

    'extern main()' which was exactly equivalent in C89 is now in C99
    presumably a constraint violation, because the declaration-specifiers
    element is present but fails to include a type specifier. Although
    6.7.2p2 is imprecisely worded and it could be read as UB-by-omission,
    but that is so inconsistent with the obvious intent I reject it.

    </> <AOL> I concur that 'int main (void)' is better.

    - David.Thompson1 at worldnet.att.net
     
    Dave Thompson, Aug 28, 2006
    #13
    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. Replies:
    2
    Views:
    424
  2. Replies:
    5
    Views:
    375
    -berlin.de
    Dec 24, 2004
  3. smartbeginner

    Allocation of memory for Array of Pointers

    smartbeginner, Dec 27, 2005, in forum: C Programming
    Replies:
    21
    Views:
    866
    Keith Thompson
    Dec 28, 2005
  4. Ken
    Replies:
    24
    Views:
    3,902
    Ben Bacarisse
    Nov 30, 2006
  5. chris
    Replies:
    6
    Views:
    1,007
    chris
    Oct 28, 2005
Loading...

Share This Page