Thread: Beginner casting and malloc/realloc question!

  1. #1
    Registered User
    Join Date
    Apr 2009
    Posts
    16

    Beginner casting and malloc/realloc question!

    EDIT: Changed some of the code around.

    Doing K&R exercise 5.13... which is supposed to take any amount of input lines and then print the last "n" lines. They wanted dynamic storage which is weird because malloc hasn't been introduced yet... so I was sort of learning this concept as I coded.

    Code:
    vchar* storeline5_13(char* line, int length)
    {
    
        static char *p;
        static char *pwalker;
    
        static int totalLength = 0;
    
        totalLength += length;
    
        if(totalLength == 0)
        {
            p = (char *) malloc(sizeof(char) * (totalLength+1));
            pwalker = p;
        }
            
        else
        {
            p = (char *) realloc(p, sizeof(char) * (totalLength+1));
            pwalker = p + (totalLength - length);
        }
            
    
        
    
        while(*line != '\n')
        {
            *pwalker++ = *line++;
        }
            
    
        *pwalker = '\0';
    
        pwalker -= length;
    
     
    
        return pwalker;
    
    
    
    }
    
    
    
    void tail5_13(int n)
    {
    
        int maxpoint = 3;
        size_t *maxlength;
        *maxlength = sizeof(char) * 10;
    
        char **pointptr = malloc(sizeof(void *) * maxpoint);
        char **pointcnt = pointptr;
    
        char *lineptr = malloc(sizeof(char) * *maxlength);
    
        int numlines = 0;
        int printnum = 0;
        int c;
    
        
    
        while((c = getline(&lineptr, maxlength, stdin)) > 2)
        {
            if(numlines < maxpoint)
            {
                *pointcnt++ = storeline5_13(lineptr, c);
            }
            else
            {
                maxpoint *= 2;
     
                pointptr = (char **) realloc(pointptr, sizeof(void *) * maxpoint);
                pointcnt = pointptr + numlines;
                *pointcnt++ = storeline5_13(lineptr, c);
            }
            numlines++;
        }
        
        if(n <= numlines)
            printnum = n;
        else
            printnum = numlines;
    
        while(printnum-- > 0 )
        {
            printf("%s\n", *(pointcnt-1));
        }
    
    }
    For some reason the pointer returned by storeline cannot be used to display the strings. I thought the way printf got strings was to take whatever characters were present from the beginning of the supplied address to '\0'. If I return the beginning pointer of the storage array (the array name) from storeline, it will correctly display the first string stored, but nothing else.

    Are my strings being stored correctly? And can someone tell me what's going on?

    I would really appreciate it
    Last edited by klawson88; 10-06-2010 at 09:02 PM. Reason: Almost solved it!

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    >>char **pointptr = malloc(sizeof(void *) * maxpoint);
    Bad, bad, bad. sizeof(void*) is not guaranteed to be == sizeof(char*) (?).

    And you are not freeing anything.
    These are merely a small amount of the problems in your code.
    Returning a static variable might not be seen as a good thing. And why reallocate? You only need a temporary buffer for returning?

    >> size_t *maxlength;
    >> *maxlength = sizeof(char) * 10;
    http://sourceforge.net/apps/mediawik...kes_and_errors
    Last edited by Elysia; 10-07-2010 at 09:29 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    Last edited by Bayint Naung; 10-07-2010 at 03:35 AM.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Link links back here.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    Apr 2009
    Posts
    16
    Thanks for your help Elysia. I've made your specified changes. That, along with the fact that the line right before the return in storeLine should have been

    Code:
    pwalker -= (length-1)
    ...seems to have been the problem. Also, prefix subtraction should have been used in the end printing.

    Here's the final code for any other people who may need it in the future (i've made changes to storeLine to make it more efficient):

    Code:
    char* storeline5_13(char** pointcnt, char* line, int length)
    {
    
        *pointcnt = (char *) malloc(sizeof(char) * length);
    
        while(*line != '\n')
            *((*pointcnt)++) = *line++;
    
    
        **pointcnt = '\0';
    
        *pointcnt -= (length - 1);
    
    
        return *pointcnt;
    
        
    }
    
    void tail5_13(int n)
    {
    
        int maxpoint = 3;
        size_t maxlength = sizeof(char) * 10;
    
        char **pointptr = malloc(sizeof(char *) * maxpoint);
        char **pointcnt = pointptr;
    
        char *lineptr = malloc(sizeof(char) * maxlength);
    
        int numlines = 0;
        int printnum = 0;
        int c;
    
        
    
        while((c = getline(&lineptr, &maxlength, stdin)) > 1)
        {
            if(numlines < maxpoint)
            {
                *pointcnt = storeline5_13(pointcnt, lineptr, c);
                pointcnt++; 
            }
            else
            {
                maxpoint *= 2;
                printf("Increased pointer amount to %d\n", maxpoint);
    
                pointptr = (char **) realloc(pointptr, sizeof(char *) * maxpoint);
                pointcnt = pointptr + numlines;
                *pointcnt = storeline5_13(pointcnt, lineptr, c);
                pointcnt++;
            }
            numlines++;
        }
        
        if(n <= numlines)
            printnum = n;
        else
            printnum = numlines;
    
        while(printnum-- > 0 )
            printf("%s\n", *(--pointcnt));
    
    }
    Last edited by klawson88; 10-07-2010 at 08:27 AM.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    In the future, restrain yourself from posting on several boards simultaneously.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Apr 2009
    Posts
    16
    Quote Originally Posted by Elysia View Post
    In the future, restrain yourself from posting on several boards simultaneously.
    Yea, its not a habit of mine but I only posted it over there when no replies came in after several hours of the topic being up here. I just assumed no one would answer.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    A couple of hours is not near enough. Patience is a virtue when it comes to boards.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Quote Originally Posted by Elysia View Post
    >>char **pointptr = malloc(sizeof(void *) * maxpoint);
    Bad, bad, bad. sizeof(void*) is not guaranteed to be the == sizeof(char*).
    char* and void* are required to be the same size.

    That said, it doesn't make semantic sense to use sizeof(void*) when you're allocating char pointers.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You are certain the standard mandates this?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    I always thought a pointer is a pointer is a pointer. That's why the format specifier is %p only, and not a bunch of things. Its size is mandated by the native machine’s happy size more than anything. Unless there are compiler overrides.

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    %p is for void* only. All pointer sizes are not guaranteed to be equal. I don't think the standard mandates that all pointers need be stored equally either. It only says that it shall be possible to convert any pointer type to void* and back without loss of information.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Quote Originally Posted by Elysia View Post
    You are certain the standard mandates this?
    Yes, both C90 (§6.1.2.5) and C99 (§6.2.5). The wording is identical: “A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.”

  14. #14
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by nonoob View Post
    I always thought a pointer is a pointer is a pointer. That's why the format specifier is %p only, and not a bunch of things. Its size is mandated by the native machine’s happy size more than anything. Unless there are compiler overrides.
    The pointer is aware of the size of the elements it points to...

    char * x; followed by x++ will increment by 1.

    long int* x; followed by x++ will increment by 4

    What I believe Elysia is trying to get across is that sizeof(void) is not defined thus
    void* x; ... x++ is unpredictable.

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by cas View Post
    Yes, both C90 (§6.1.2.5) and C99 (§6.2.5). The wording is identical: “A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.”
    Ah, my mistake then. Thanks for the clarification.

    Quote Originally Posted by CommonTater View Post
    The pointer is aware of the size of the elements it points to...

    char * x; followed by x++ will increment by 1.

    long int* x; followed by x++ will increment by 4

    What I believe Elysia is trying to get across is that sizeof(void) is not defined thus
    void* x; ... x++ is unpredictable.
    No, and incrementing and dereferencing a pointer to void is not allowed AFAIK.
    It's just that pointer sizes and their byte representations are not guaranteed to be the same, save for void* and char*.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. srdup question
    By owi_just in forum C Programming
    Replies: 2
    Last Post: 03-20-2005, 03:42 AM