Search code examples
cpointersconstants

Why is "const char * const" not used as input string argument for a function in C?


Here is a useful reminder about pointers in C:

int       *      mutable_pointer_to_mutable_int;
int const *      mutable_pointer_to_constant_int;
const int *      mutable_pointer_to_constant_int;
int       *const constant_pointer_to_mutable_int;
int const *const constant_pointer_to_constant_int;
const int *const constant_pointer_to_constant_int;

Now, let's say I have a function do_something that takes a string as input. The string will not be modified. I would write something like this:

void do_something(char const* const string);

Here's the thing: when looking at API code provided by microcontroller manufacturers (which is supposed to be well written), in such a case, I rarely see the type char const * const used as an input type. Instead, they typically write char const* string or const char* string.

Is there a specific reason for this? Wouldn't it be cleaner to make the pointer itself const as well?

Thank


Solution

  • Let's look at a simpler case first.

    Given

    void do_something1( int i ) { ... }
    
    void do_something2( const int j ) { ... }
    

    The following applies:

    • i is an object of type int.
    • j is a constant object of type int.

    So,

    • do_something1 would be allowed to modify i, and the following is valid:

      void do_something1( int i ) {
         ++i;  // ok
         printf( "%d\n", i );
      }
      
    • do_something2 would be not allowed to modify string2, and the following is invalid:

      void do_something2( const int j ) {
         ++j;  // ok
         printf( "%d\n", j );
      }
      

    Keep in mind that parameters are local to their function, so changes to them have no effect in the caller. So making the parameter const only serves to shackle the writer of the function. The benefits of doing so are elusive to me.


    The same applies in your code.

    Given

    void do_something3( char const *s ) { ... }
    
    void do_something4( char const * const t ) { ... }
    

    The following applies:

    • s is a pointer to a constant object of type char.
    • t is a constant pointer to a constant object of type char.

    So,

    • do_something3 would be allowed to modify s, and the following is valid:

      void do_something3( char const *s ) {
         while ( *s ) {
            putchar( *s);
            ++s;  // ok
         }
      }
      
    • do_something2 would be not allowed to modify t, and the following is invalid:

      void do_something4( char const * const t ) {
         while ( *t ) {
            putchar( *t );
            ++t;  // XXX
         }
      }
      

    Again, keep in mind that parameters are local to their function, so changes to them have no effect in the caller. So making the parameter const only serves to shackle the writer of the function. The benefits of doing so are elusive to me.