C Language

You Can't Get There from Here

In C, you can also create "dangling" pointers - ones that point somewhere, but not where you'd expect. Figure 6.5 shows a function intended to return a month's name, given the month's number. This function will be compiled, will run, and will return a non-null character pointer. But the returned pointer will point to memory allocated only temporarily to the names array. When the month_name function returns, the names array will be deallocated, and another function's local (automatic) variables may reuse its memory. Using the pointer value returned by month_name may result in a month Pope Gregory never contemplated - or worse, another frozen machine. Functions patterned after Pascal's built-in new pointer function offer some help. To conveniently and safely allocate a new string and assign it a value, first use C's typedef feature to make a meaningful name for C's "string" type:

 typedef char * string_t;

Here, I follow the common convention of ending typedef names with "_t". C typedef names are synonyms for explicit C type specifications and help make your C programs more readable. (In Chapter 4, I describe a more comprehensive way to deal with strings in C. In this chapter, I cover only conventional C string-handling. You can combine suggestions from both chapters to build your own complete string facility.)

Figure 6.5 Creating a Dangling Pointer

 char* month_name( const int month ) {
   /*
   | Return month name
   */
   char names[10][12] = {
     "January", ... "December" };
  return names[ month - 1 ];
 }

Figure 6.6 uses string_t to declare parameters for the function new_string. (A similar function, strdup, is available in Microsoft C but not in ANSI C.) With this function, it's easy to write a correct version of month_name, as shown in Figure 6.7. Like Figure 6.5's incorrect version, the corrected version returns a character pointer. However, the pointer returned by the corrected version points to memory that remains allocated and that contains the desired month name.

Figure 6.6 new_string Function

 string_t function new_string( const string_t val ) {
    /*
    | Allocate and load storage for string val
    |
    | Return pointer or NULL, if error
    */
    string_t p;
    if ( val == NULL ) {
       printf( "Invalid NULL value pointer\n" );
       return NULL;
    }
    p = (string_t) malloc( strlen( val ) + 1 );
    if ( p == NULL ) {
       printf( "No memory for %s\n", val );
       return NULL;
    }
    else {
      strcpy( p, val );
      return p;
    }
  }

Figure 6.7 Corrected month_name Function

 char * month_name( const int month ) {
    /*
    | Return month name
    */
    char names[10][12] = {
      "January", ... "December" };
    return new_string( names[ month - 1 ] );
 }

by BrainBellupdated
Advertisement: