3

I was reading though this: const char * const versus const char *?

in string.h, strlen is defined as:

size_t strlen ( const char * str );

If I understand this correctly, strlen expects a pointer to a char that is const. Shouldn't it be:

size_t strlen ( const char* const str );

This would make sure that strlen cannot modify the pointer to point to a different pointer ?

Or, is this the case:

Since str pointer will be passed by value to strlen, any changes to this pointer in the function will not change the source pointer, and hence it's okay..

??

Community
  • 1
  • 1
brainydexter
  • 19,826
  • 28
  • 77
  • 115
  • 2
    `strlen()` cannot modify the pointer you pass in, in either case; it receives a copy. This would only be relevant if you passed in a pointer-to-pointer. – cdhowie Jul 26 '12 at 17:03
  • Those functions have the same signature. See also: http://stackoverflow.com/questions/11645751/why-are-const-qualifiers-in-function-arguments-used-for-overloading-resolution http://stackoverflow.com/questions/4212932/defining-a-function-with-different-signature http://stackoverflow.com/questions/3682049/functions-with-const-arguments-and-overloading and many more. – CB Bailey Jul 26 '12 at 17:31

3 Answers3

12

If you really read that discussion, you should understand that the second const has no effect on the external behavior of the function. For you, the user of strlen, It simply doesn't make any difference whether it is declared with const char * or const char *const parameter. As you correctly noted, any modifications that strlen might do to the pointer are only affecting the internal, local copy of the pointer inside strlen. Your argument pointer that you pass to strlen will remain unchanged regardless of whether the parameter is declared with second const or not. (Your argument pointer doesn't even have to be an lvalue.)

The second const will only have effect on the internal behavior of the local parameter variable inside the function, preventing the authors of strlen from modifying that local variable. Whether they want to restrict themselves in that way or not is, informally speaking, their own business. It doesn't concern the users of strlen in any way.

In fact, since top-level const qualifiers have no effect on function type, it is typically possible to declare a function with const char * parameter and then define it with const char *const parameter. The compiler (linker) will still treat these declarations as "matching". It means that if the library authors so desired, they could actually define strlen with const char *const parameter. They are simply not telling you about that, since this is effectively an implementation detail or strlen, i.e. something you don't need to know.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    +1, the standard is explicit in that the *top-level* const-volatile qualifier (in this case the second `const`) is dropped from the signature of the function. – David Rodríguez - dribeas Jul 26 '12 at 17:01
  • @AndreyT: Thanks for explaining that so well, and also giving me a practical use case of how to use it with the `declare`/`define` construct! – brainydexter Jul 26 '12 at 17:10
2

Since str pointer will be passed by value to strlen, any changes to this pointer in the function will not change the source pointer, and hence it's okay..

Yes. It's only a restriction for the functions interior handling.

This would make sure that strlen cannot modify the pointer to point to a different pointer ?

It's not needed, the pointer is passed by value.

Zeta
  • 103,620
  • 13
  • 194
  • 236
2

size_t strlen ( const char* const str );

This would make sure that strlen cannot modify the pointer to point to a different pointer ?

You explained the reason yourself : strlen cannot modify the pointer....

It unnecessarily imposes restriction on the parameter, which could be used to compute the length while modifying the pointer itself, as:

 size_t len = 0;
 while(*str)
 {
   ++len;
   ++str; //error if `const char *const str` is used!
 }

See the implementation of strlen() in glibc which modifies the pointer itself: by assigning it to modifiable pointer type.

See also OpenBSD lib implemtation:

size_t strlen(const char *str)
{
    const char *s;

    for (s = str; *s; ++s)
        ;
    return (s - str);
}

Here s=str would be error if str is const char * const type!

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851