20

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 const before char (void foo(const char arr_arg[])) or after char(void foo(char const arr_arg[])), that would mean than it's char which is constant, not the arr_arg.

I have just read that under the hood an array sent as a parameter to function is represented as a pointer, so void foo(char arr_arg[]) is the same as void foo(char* ptr_arg). Taking it into account, I may rewrite the function as void foo(char * const ptr_arg) for it to be exactly what I want to achieve.

But I want to know if there is a way to add const keyword in this declaration void foo(char arr_arg[]) for it to be the same as void foo(char * const ptr_arg) (and not void foo(char const * ptr_arg) or void foo(const char * ptr_arg))?

I just want to understand if there is a syntax to make arr_arg constant with array notation [].

13
  • 4
    is there any specific reason you don't want to do void foo(char * const ptr_arg)? It's exactly the same syntax everywhere else. You can still do ptr_arg[0] as if it was declared as an array. Commented Jun 6, 2012 at 20:19
  • @Hans I just want to understand if it's syntactically possible to do it with array notation []. No specific reason. Just want to clarify if it's possible or not (just to know in the future and not waste time contemplating if it's possible or not again and again). Commented Jun 6, 2012 at 20:21
  • I don't think there's any need to declare the pointer itself as const as it will be passed by value anyway. Only if you explicitely want to protect from assigning (the copy of the pointer on the stack) inside of the functions definition. Commented Jun 6, 2012 at 20:27
  • May be it's possible syntactically in conjunction with the & (reference) operator. Didn't try that so far, but may be it could matter with fixed length arrays. Commented Jun 6, 2012 at 20:31
  • 1
    Wait, is this question C or C++? Because as some of the answers have observed, they are very very different in this regard. Commented Jun 6, 2012 at 20:48

5 Answers 5

23

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.

Sign up to request clarification or add additional context in comments.

13 Comments

Thanks! I'll accept the answer in a few minutes (when SO will let me do that). Could you write a few words about what C99,C89/90 are (for those who will be reading this answer, for part of them not to search Google to clarify what they are)?
@ovgolovin added in C99 in 6.7.5.3p7
@ovgolovin: Note that the argument is still not an array, but a pointer, and that pointer is copied, which means that the original pointer (and array) cannot be changed inside the function. If you are talking about real arrays (rather than dynamically allocated memory), then the array is immutable (the contents can be changed, but the array as a container cannot) so it makes little sense to mark it as const
@DavidRodríguez-dribeas I really don't understand what is the sense of having array const (I just asked about syntactic possibility to do that). But if a new standard C99 allows it, it mean there are some reasons to allow to declare the array this way.
@ovgolovin: As David noted, in this case it is not the array, it is the pointer that gets declared as const. Firstly, this might be useful when supporting coding standards that require all function parameters to remain unchanged (and possibly explicitly declared as const). Secondly, the feature was probably introduced to support other, "more useful" specifiers in this context, like restrict and static, while const just tagged along for the ride.
|
14

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.

Comments

2

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.

2 Comments

@MooingDuck, I never said that it is for C++, by I now emphasize on C. And the OP still claims that he is interested in C, too, so this answer does no harm.
Sorry for mistagging. I just thought it's the same in C and C++. But then when I was asked, I left only C++ (which compiler I'm using now). But in fact it's very interesting to know about C as well. Now I know that it was impossible and became possible only with the come of C99.
2

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

2 Comments

Isn't void f0(const array a) the same as void f0(const char * a) (which makes char constant, not a)?
nope, array is a full type, and const array makes a const variable of type array. It's a very common trick when passing around function pointers, since otherwise the syntax is unwieldy.
0

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.

2 Comments

Careful with that second, as it is different than asked for and all the other answers on the page. The data that the array points at is local, and also const.
@MooingDuck: I modified the answer to point out the advantage of using Boost::array over a C style array in C++, and +1 on your post.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.