Thread: Simulating the string class - your comments on this, please

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    204

    Simulating the string class - your comments on this, please

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int i, c;
        char *input;
    
        i = 0;
    
        printf("Type something: ");
        c = getchar();
    
        input = malloc(1 * sizeof(c));
        if (input == NULL)
            return 1;
    
        input[i++] = c;
    
        while ((c = getchar()) != EOF && c != '\n') {
            if ((realloc(input, 1 * sizeof(c))) == NULL)
                return 1;
            input[i++] = c;
        }
    
        input[i] = '\0';
    
        printf("%s\n", input);
    
        free(input);
    
        return 0;
    }
    Thank you.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You mean other than the fact that you throw away the return of realloc?


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    204
    Can you elaborate, please?

  4. #4
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    If successful, realloc() returns a pointer to the new memory just allocated. While you check to see if that return value is NULL or not, you don't do anything else with the pointer. I think that is what quzah was getting at. If the original block of memory that you got with malloc() cannot be resized, then realloc() will give you a new, different block, and if this is the case, then you want to use the pointer returned by realloc, and not the old pointer that you originally had.
    Last edited by kermit; 08-25-2005 at 07:59 PM.

  5. #5
    aoeuhtns
    Join Date
    Jul 2005
    Posts
    581
    You never want to use realloc without assigning the return value to something. Suppose you want to realloc the array pointed to by x, to the size y. The expression realloc(x, y) will return a pointer to an array of size y whose first n elements (where n was the size of the array pointed to by x) are equal to those of x. If y > x, then this might be a new location! Which means that the pointer x is no longer pointing to a valid memory address.

    As a result, you generally want to use x = realloc(x, y);

    What bothers me is that in your case, you are not actually changing the size of the array. You malloc'd your array to size 1 * sizeof(c) and you're realloc'ing your array to the size 1 * sizeof(c). Since c is an int, and since ints are usually four bytes wide nowadays, your array is going to be four characters wide. Since you're not changing the size of the array, input will still be pointing to a valid memory address (since a new one won't be used). This might or might not be guaranteed by C standards.

    What then happens is that you might increment i four times. And if that happens, then you've incremented i into uncharted territory, and you're going to be writing over uncharted memory.

    I recommend re-reading up on how realloc works.

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Rashakil Fol
    As a result, you generally want to use x = realloc(x, y);

    ...snip...

    I recommend re-reading up on how realloc works.
    Actually, the best way to do it is like so:
    Code:
    z = realloc( x, y );
    Because if realloc fails, it's going to return NULL, and in doing so, you have just lost x in your example. The best way is as shown above, then test z to see if it's NULL. If it isn't you're good to go, if it is, you at least haven't lost x. But I agree with your recommendation.


    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    204
    Is this correct now?
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int i, c;
        char *input;
    
        i = 0;
    
        printf("Type something: ");
        c = getchar();
    
        input = malloc(1 * sizeof(c));
        if (input == NULL)
            return 1;
    
        input[i++] = c;
    
        while ((c = getchar()) != EOF && c != '\n') {
            input = realloc(input, 1 * sizeof(*input) + 1 * sizeof(c));
            if (input == NULL)
                return 1;
            input[i++] = c;
        }
    
        input[i] = '\0';
    
        printf("%s\n", input);
    
        free(input);
    
        return 0;
    }

  8. #8
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    No. sizeof(*input) will always be 1, even if you're previously allocated more memory for the input pointer. You need to keep track of the size of the buffer in a separate variable. input is just a pointer to a single byte (char), it has no concept of size beyond that.

    Also, although getchar returns an int, when you assign it to a deference of input, it becomes a char, since input is a pointer to char.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    204
    Hum, so the variable i would be the perfect argument for the realloc function, right? Something like this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int i, c;
        char *input;
    
        i = 0;
    
        printf("Type something: ");
        c = getchar();
    
        input = malloc(1 * sizeof(c));
        if (input == NULL)
            return 1;
    
        input[i++] = c;
    
        while ((c = getchar()) != EOF && c != '\n') {
            input = realloc(input, i + 1);
            if (input == NULL)
                return 1;
            input[i++] = c;
        }
    
        input[i] = '\0';
    
        printf("%s\n", input);
    
        free(input);
    
        return 0;
    }

  10. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Code:
    while ((c = getchar()) != EOF && c != '\n') {
            input = realloc(input, i + 1);
    Except you're still not listening to what we've been saying with realloc. If it fails, you kill your buffer doing it this way, because it assigns NULL to 'input', leaking anything you used to have there. It may not make much of a difference in this small program you're using now, but do it later in a program where you actually try and recover, or exit "nicely", and you'll not like the result. Read my last post again.


    Quzah.
    Hope is the first step on the road to disappointment.

  11. #11
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    Probably. A few more points:

    You are still originally malloc'ing sizeof(int), but you only need 1 byte for the first char.

    malloc/realloc are relatively expensive operations, so in the real world, you would likely want to malloc/realloc larger chunks at a time as you need them, instead of each time a new character needs appending.

    Follow quzah's advice to use a different variable for the return value of realloc to the thing you are trying to realloc. Although you are ending the program as soon as realloc fails, it is good practice to call free on the original untouched pointer before failing. This would be especially appropriate if you had this in a function, rather than a whole program that terminates on realloc failure.

    (edit: last paragraph becomes semi-redundant, I didn't see quzah's last post before submitting)

  12. #12
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Overkill, by the time I replied, but...
    Quote Originally Posted by caduardo21
    Code:
    input = realloc(input, i + 1);
    https://cboard.cprogramming.com/showthread.php?p=367853

    [edit]
    Quote Originally Posted by cwr
    No. sizeof(*input) will always be 1
    And here generally I draw a distinction -- sizeof(char) will always be 1, sizeof *input may not.
    Last edited by Dave_Sinkula; 08-25-2005 at 08:55 PM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  13. #13
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    Quote Originally Posted by Dave_Sinkula
    [edit]And here generally I draw a distinction -- sizeof(char) will always be 1, sizeof *input may not.
    I probably wasn't explaining very clearly, but I meant that sizeof(*input) will always be the size of what input is a pointer to, in this case, a char.

    The original poster's code suggested he was under the impression that as his "array" grew, sizeof(*input) would evaluate to a larger and larger value.

    Obviously, if the code is changed and input is changed to point to something other than a char, then sizeof(*input) will be different.

  14. #14
    Registered User
    Join Date
    Jan 2005
    Posts
    204
    Thanks Dave. So, does it look good now?
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int i, c;
        char *input;
        char *temp;
    
        i = 0;
    
        printf("Type something: ");
        c = getchar();
    
        input = malloc(1 * sizeof(c));
        if (input == NULL)
            return 1;
    
        input[i++] = c;
    
        while ((c = getchar()) != EOF && c != '\n') {
            temp = realloc(input, i + 1);
            if (temp == NULL) {
                free(input);
                return 1;
            }
    
            input = temp;
            input[i++] = c;
        }
    
        input[i] = '\0';
    
        printf("%s\n", input);
    
        free(input);
        free(temp);
    
        return 0;
    }

  15. #15
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    One more time! All together with me!
    Code:
    int i, c;
    
        ...
    
        input = malloc(1 * sizeof(c));
    "The sizeof c is not what you want! Why do you keep doing this?"

    Also, what's the point of multiplying by 1? Is sizeof( foo ) not enough? It must be "1 * sizeof( foo )"?


    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. String Class
    By BKurosawa in forum C++ Programming
    Replies: 117
    Last Post: 08-09-2007, 01:02 AM
  2. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  3. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  4. Replies: 4
    Last Post: 03-03-2006, 02:11 AM
  5. class object manipulation
    By guda in forum C++ Programming
    Replies: 2
    Last Post: 10-09-2004, 10:43 AM