Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C, is it legal to add `const` only in function definitions, not declarations?

Tags:

c

constants

c99

Is adding additional const specifiers to function arguments allowed by the standard, like in the following?

foo.h:

int foo(int x, char * data);

foo.c:

// does this match the prototype?
int foo(const int x, char * const data) {
    // this implementation promises not to change x or move data inside the function
}

GCC accepts it with -std=c99 -Wpedantic -Wall -Werror, but that's not necessarily the same as standard-compliant.

This answer shows that the C++ standard allows this - does the C (99) standard allow this too?


There's another question here and a good answer here for C++

like image 475
Eric Avatar asked Sep 22 '17 21:09

Eric


2 Answers

This is explicitly allowed by a special case in the rules for function parameter lists. N1570 §6.7.6.3p131 says:

In the determination of type compatibility and of a composite type, each parameter declared with function or array type is taken as having the adjusted type and each parameter declared with qualified type is taken as having the unqualified version of its declared type.

But you must also understand that the "unqualified version" of a type like const char * is still const char *, because the type const char * is derived from the type const char, and §6.2.5p26 says

A derived type is not qualified by the qualifiers (if any) of the type from which it is derived.

That means that the declaration

void foo (const int x);

is compatible with the definition

void foo (int x) { ... }

but the declaration

void bar (const char *x)

is not compatible with the definition

void foo (char *x) { ... }

You might be wondering why these rules are the way they are. The short version is that in C, all arguments are always passed by copying the value (but not any data pointed to by the value, if there are pointers involved), so it doesn't matter whether an actual argument is const T; the callee receives it as a regular old T regardless. But if you copy a pointer to constant data, the copy still points to constant data, so it does matter and that qualifier should be preserved.


1 Document N1570 is the closest approximation to the 2011 ISO C standard that is publicly available at no charge.

To the best of my knowledge, these rules have not changed significantly since the original 1989 standard. Pre-C89 "K&R" C didn't have prototypes, nor did it have const, so the entire question would be moot.

like image 137
zwol Avatar answered Sep 30 '22 21:09

zwol


From the C99 spec, 6.7.5.3.15 Function declarators, this is legal:

If one type has a parameter type list and the other type is specified by a function definition that contains a (possibly empty) identifier list, both shall agree in the number of parameters, and the type of each prototype parameter shall be compatible with the type that results from the application of the default argument promotions to the type of the corresponding identifier. (In the determination of type compatibility and of a composite type, each parameter declared with function or array type is taken as having the adjusted type and each parameter declared with qualified type is taken as having the unqualified version of its declared type.)

like image 36
Eric Avatar answered Sep 30 '22 21:09

Eric