RSS

C/C++ Constness

Constness Post Banner

An aide-memoire post about using the const keyword in function declarations in C/C++. This keyword can have two meanings for pointers depending upon where it is placed:

  • The pointer is constant and cannot be changed
  • The data pointed to by the pointer is constant and cannot be changed

The following application will be used to illustrate the various cases:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void func(char *string)
{
    printf("%s\n", string);
    printf("%s\n", ++string);
    *string = 's';
    printf("%s\n", string);
}

int main(int argc, char**argv)
{
    char *str = strdup("Hello, World!");
    func(str);
    
    free(str);
    return(0);
}

The focus on the definition for func to illustrates the differences. The code fragments that follow will focus on just the definition of func as the rest of the code remains unchanged.

Simple Cases – No const, All const

There are two simple cases:

  • No const – both pointers and data can be changed
  • Both parameters are const – both data and pointer cannot be changed

In the first case, no const, we have the following code:

void func(char *string)
{
    printf("%s\n", string);
    printf("%s\n", ++string);
    *string = 's';
    printf("%s\n", string);
}

Compiling and running this application results in the following output:

Hello, World!
ello, World!
sllo, World!

As we can see, the pointer string and the data pointed to by string can both be changed.

Modifying the code to make make both the pointer and the data pointed to by the pointer string constant, the function definition becomes:

void func(const char * const string)
{
    printf("%s\n", string);
    printf("%s\n", ++string);
    *string = 's';
    printf("%s\n", string);
}

Compiling the application generates the following output:

Const.c:8:20: error: cannot assign to variable 'string' with const-qualified type 'const char *const'
    8 |     printf("%s\n", ++string);
      |                    ^ ~~~~~~
Const.c:5:30: note: variable 'string' declared const here
    5 | void func(const char * const string)
      |           ~~~~~~~~~~~~~~~~~~~^~~~~~
Const.c:9:13: error: read-only variable is not assignable
    9 |     *string = 's';
      |     ~~~~~~~ ^
2 errors generated.

This shows that these lines contain logic errors:

printf("%s\n", ++string);
*string = 's';

This is expected as printf(“%s\n”, ++string); attempts to modify the pointer and *string = ‘s’; attempts to modify the data.

Making the Pointer Constant

The definition of func can be modified to make just the pointer constant and allow the data to be modified:

void func(char * const string)

Compiling the application generates the following output from the compiler:

Const.c:8:20: error: cannot assign to variable 'string' with const-qualified type 'char *const'
    8 |     printf("%s\n", ++string);
      |                    ^ ~~~~~~
Const.c:5:24: note: variable 'string' declared const here
    5 | void func(char * const string)
      |           ~~~~~~~~~~~~~^~~~~~
1 error generated.

Making the Data Constant

There are two ways of allowing the pointer to change wile maintaining the integrity of the data:

void func(const char *string)

and

void func(char const *string)

Compiling an application with either of these function definitions generates and error such as:

Const.c:9:13: error: read-only variable is not assignable
    9 |     *string = 's';
      |     ~~~~~~~ ^
1 error generated.

Function definitions such as the above are useful for functions such as strlen where we want to walk through an array of data in a read-only mode.

Conclusion

This post aims to clear up the confusion about what is constant given that const can appear on both the left and right side of a variable in a function definition. The following table summaraises what is constant for the various options for const:

Definition Description
void func(char *string) Both the data and the data pointed to by string can be changed.
void func(const char * const string)
void func(char const * const string)
The pointer string and the data pointed to by void func(char const * const string) are both constant.
void func(char * const string) The pointer is constant and cannot be changed.
void func(const char *string)
void func(char const *string)
The data pointed to by string is constant.

So the general rule is the item to the left of the const key word is the item that cannot be changed. With one exception and that is when a variables type is prefixed by const. In which case the const applies to the type and not any pointer definition.

Tags: ,

Saturday, November 1st, 2025 at 12:01 am • Aide-memoir, aide-memoire, Software DevelopmentRSS 2.0 feed • leave a response or trackback

Leave a Reply

*