Thread: using a char *

  1. #1
    Registered User
    Join Date
    Apr 2007
    Posts
    28

    using a char *

    Just a little clarification, please:

    If I use malloc, where CHAR_BUFFER_SIZE is previously defined to 256, for example:

    Code:
    char* name = (char *)malloc(CHAR_BUFFER_SIZE);
    I need to free it somewhere using:

    Code:
    free(name);
    If this variable name is a return value, can you explain a bit for me the best way to proceed?

    Just for simplicity, if there's a function, for example:

    Code:
    void test()
    {
         char* name = (char *)malloc(CHAR_BUFFER_SIZE);
         name = getName();
    
         printf("Name = %s", name);
    
         name = reverseName(name);
         printf("Name = %s", name);
    
         free(name);
    }

    Code:
    char* getName()
    {
        char* name = (char *) malloc(CHAR_BUFFER_SIZE);
        
        // ..... whatever code here
        return name;
    }
    Code:
    char* reverseName(char* name)
    {
        char* newName = (char *) malloc(CHAR_BUFFER_SIZE);
        
        // ..... error check here for newName to see if malloc worked
        // ..... error check here for name for validity
        // ..... code here to reverse the name ...
    
        return newName ;
    }
    Now in this function I have a char* called name, however -- it calls a function getName which returns a char*.

    Is it better to pass it in as a parameter instead? How do I send a char pointer to a function?

    The same goes for reverseName(), it would be better written to send in a char pointer as well (the address of), create the newName with the reversed letters, copy it back to the char* name sent in, and free(newName).

    If I understand it right... and then I wouldn't have to use:

    Code:
    name = reverseName(name);
    Thanks....

  2. #2
    Registered User Noir's Avatar
    Join Date
    Mar 2007
    Posts
    218
    Code:
    name = reverseName(name);
    Okay, name already points to dynamic memory, but you reuse it for the return value, so you lose the reference to the original memory and have a leak. At the least you need to use two separate pointers so you can free both blocks:
    Code:
    char *name;
    char *rname;
    
    ...
    
    rname = reverseName( name );
    
    ...
    
    free( name );
    free( rname );
    How do I send a char pointer to a function?
    If you need to allocate memory to it, you pass a pointer to the pointer:
    Code:
    char* reverseName( char** name )
    {
      *name = malloc( CHAR_BUFFER_SIZE );
        
      ...
    
      return *name;
    }
    A much better way in my opinion is to handle the memory outside of reverseName and just pass the array along with the size:
    Code:
    void reverseName( char name[], int size ) {
      // reverse the array
    }
    
    int main( void ) {
      char *name = malloc( CHAR_BUFFER_SIZE );
    
      ...
    
      reverseName( name, CHAR_BUFFER_SIZE );
    
      ...
    
      free( name );
    
      return 0;
    }

  3. #3
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    You pass a char * to a function just like you would with any other object. Pointers are objects too.

    For instance, your main concern is with how pointers are returned from functions. The simplest answer is for any pointer bar, the state of the pointer returned depends on two things: what address bar is pointing to and how the memory at that address was allocated. If name were automatic, say

    char name[CHAR_BUFFER_SIZE];
    ...
    return name; /* return its pointer: &name[0] */

    Automatic memory is usually declared at the beginning of a new block of code marked with a curly brace. Since name uses automatic memory, as soon as execution runs to the end of the code block it was declared in, name would be deallocated, making all pointers to that memory location wild! (There is no char * object at that address.) But attempting to use automatic memory by giving it a broad enough scope is a Smart Thing, because we don't have to juggle calls to malloc and free, as you're discovering. (Although, malloc and free have a similar rule: structure your program so that calls to malloc and free occur in the same scope.)

    Lecture aside, the way that you're doing things now would be OK if you were able to free all the memory you allocated with malloc at some point. I don't see where newName is deallocated, so this leads to potential problems, like memory leaks.

    My advice is to do this at first with automatic memory. You can incorporate dynamic memory later.

    .... *sigh* beaten.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > name = getName();
    This leaks memory, you lost the original value stored in name.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Apr 2007
    Posts
    28
    Thanks everyone for helping... another question though.

    I have:

    Code:
    char* name = malloc(CHAR_BUFFER_SIZE);
    
    if (name)
    {
        // do whatever I need
    }
    I thought I was supposed to, or should, check to see if malloc allocated name...

    However, when I use:

    Code:
    char* name;
    
    // name = malloc(CHAR_BUFFER_SIZE);
    
    if (name)
    {
        // ... do whatever ...
    }
    This code goes into the if (name) ...

    I looked it up a bit, and I found examples that check to see if name was not equal to NULL after using malloc.

    Why does my if (name) section get reached if I comment out the malloc section?

    Confused? Shouldn't this fail?

  7. #7
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    If name hasn't been initialized, it could point to any random number. In C, 0 is false, and everything else is true. This means that if name does not point to 0 (ie. NULL), the expression if(name) will be resolved as true.

  8. #8
    Registered User
    Join Date
    Apr 2007
    Posts
    28
    So checking for malloc to have done something means two things to me:

    1. Either set the char* name = NULL
    And then the
    Code:
    if (!name) { }
    will fail if malloc didn't do it's job.

    Is that overkill for each char* ... seems like a lot of extra setting to NULL -- and the compiler complains each time. (Dumb warning, but there nonetheless).

    2. Leave it as char* name;
    Use malloc = ....
    Don't bother to check, since the results are kind of garbage.

    Okay.

    Which way do I go? One thing says to check before using the char* for it to have been initialized, and the next thing points to not being able to check.

  9. #9
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    If you set a char * to point to whatever malloc() returns, it will either be a valid memory address, or NULL. Just remember to always do something with a pointer before using it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ ini file reader problems
    By guitarist809 in forum C++ Programming
    Replies: 7
    Last Post: 09-04-2008, 06:02 AM
  2. Sorting Linked Lists
    By DKING89 in forum C Programming
    Replies: 6
    Last Post: 04-09-2008, 07:36 AM
  3. code condensing
    By bcianfrocca in forum C++ Programming
    Replies: 4
    Last Post: 09-07-2005, 09:22 AM
  4. Passing structures... I can't get it right.
    By j0hnb in forum C Programming
    Replies: 6
    Last Post: 01-26-2003, 11:55 AM
  5. String sorthing, file opening and saving.
    By j0hnb in forum C Programming
    Replies: 9
    Last Post: 01-23-2003, 01:18 AM