Is there any way that I can add const
keyword to an array passed as a parameter to function:
void foo(char arr_arg[])
If I place <
There's several ways in C++, but none are quite what you seem to be expecting.
//typedef has a very clear intent
typedef char* array;
void f0(const array a) {}
//switch to pointers to sidestep the problem
void f1(char* const a) {}
//references are inherently const
//can't take pointers, but guarantees the size, sometimes nice
//this version obviously doesn't work in C
template<int n>
void f2(char (&a)[n]) {}
http://ideone.com/4LvYT
In C you have to put const
between the []
, however strange that might look to an unprepared person
void foo(char arr_arg[const]);
This is "new" C99-specific syntax. In C89/90 or C++ there no way to do it with "array" syntax, so you have to switch to the equivalent "pointer" syntax, as suggested in David's answer.
Yes, in C this is possible since C99:
void foo(char ptr_arg[const]);
is valid syntax and equivalent to
void foo(char *const ptr_arg);
More generally the []
may contain any type qualifier, static
and an integer expression. But
The optional type qualifiers and the keyword
static
shall appear only in a declaration of a function parameter with an array type, and then only in the outermost array type derivation.
that is for the dimension that is equivalent to the pointer declaration.
The first thing is that in your particular signature, the argument is transformed by the compiler into a pointer, so what you have is:
void foo( char * arg );
Now, there are two entities that can be made const in that signature: the pointer and the pointed type. To make the pointed type can be made const in two different yet equivalent ways [*]:
void foo( const char * arg );
void foo( char const * arg );
The pointer could be made const with the syntax:
void foo( char * const arg );
But note that in a function signature, in the same way that char arg[]
is transformed into a pointer char *arg
, the top level qualifier is discarded. So from the point of view of the declaration, these two are equivalent:
void foo( char * const arg );
void foo( char * arg );
In the definition, the top level const can be use to instruct the compiler that the argument pointer (by value) should not be changed within the function, and it will detect if you attempt to reset the pointer to a different location. But, if only the pointer is const, then the compiler will gladly let you modify the pointed memory. If you don't want the function to change the contents of the array, then you should opt for one of the first two signatures.
[*] I tend to prefer the char const *
format, as it provides a consistent way of reading types: from right to left it reads: a non-const pointer to a const char. Additionally it is simpler to reason about typedef-ed types (by performing direct substitution in the expression). Given typedef char* char_p;
, const char_p
and char_p const
are both equivalent to char * const
and different from const char *
. By consistently using const
on the right you can just blindly substitute the typedef and read the type without having to reason.
For C++, Mooing Duck's answer using the template is the most straight forward.
If you have C code that is calling a C interface implemented in C++, you are stuck with converting the argument into a pointer argument instead, and making that const
If you were to use Boost's array instead of using C arrays directly, then you would be able to make that const
, although it would also be a template function:
template <unsigned N>
void foo (Boost::array<char, N> const & arg) {}
The advantage of Boost::array
is that it gives you the ability to do a light weight allocation of an array off the stack, but be able to fully use STL algorithms that depend upon traits in the container.