Does f (mystruct * a) change to f (const mystruct * a) violates API / ABI in C?

1: void f(mystruct *a) 2: void f(const mystruct *a) 

Is changing the signature of a function from 1-> 2 to break the API / ABI in C?
How about change 2-> 1?

+7
source share
5 answers

From standard C99 6.2.5 / 26 β€œTypes”:

pointers to qualified or unskilled versions of compatible types must have the same presentation and alignment requirements.

Thus, the ABI / API should not be affected from 1 to 2. (The API does not change, because a pointer to a non-constant type can be converted to a version pointer, the type is 6.3.2.3/2 "Conversions - Pointers").

However, if you go from 2 to 1, then the API changes because the pointer to a const object cannot be implicitly converted to a pointer to a non-constant object. The following code will compile according to version 2, but will not compile according to version 1:

 static const mystruct foo; f(&foo); 
+5
source

Except as indicated in the two previous answers, coming from 1-> 2, it may or may not violate the API. It depends on the base type of mystruct . The API will break if mystruct is not specified mystruct will be a typedef for the array type.

 typedef struct toto mystruct[1]; 

For such a beast

 mystruct A; f(&A); 

the f call will be valid until the API changes, but will subsequently be invalid.

+4
source

It depends on what you mean by the API. At compile time, a T * can always be implicitly converted to const T * (Note: except for the exception that Jens Gustedt pointed out in his answer!). The converse is not true; a const T * will not be implicitly converted to T * , so a throw is always required to avoid a compiler error. Therefore, if you change the declaration of an interface function from const to not const , then none of your client codes will be compiled. (You can get around this simply by discarding const -ness in all calls, but this should be avoided if it is absolutely inevitable, because the behavior is undefined, which means that you violated your own interface).

At the bit level (i.e., ABI) there will be no difference between the representations of your pointers or objects. However, not to say that the compiler did not perform optimizations / assumptions based on what is labeled const when the generated machine code processes these representations; if you drop const -ness, these assumptions may no longer hold and the code will break.

+3
source

As for ABI, no, then const only affects errors at the compilation stage. Compiled object files should not have any const constants.

+2
source
 OLD: void f(mystruct *a) NEW: void f(const mystruct *a) 

ABI: If a was an out parameter, then old applications may be corrupted.

API: It seems to be compatible.

 OLD: void f(const mystruct *a) NEW: void f(mystruct *a) 

ABI: The function f may try to change the value of a parameter that should not be changed by old applications.

API: Compiler Error.

EDIT (1): This is an example showing a compiler error than changing a non-constant parameter:

library header.h:

 struct mystruct { int f; }; void f(struct mystruct *a); 

Application:

 int main() { const struct mystruct x = {1}; f(&x); return 0; } 

compiler error ( gcc -Werror app.c ):

 error: passing argument 1 of 'f' discards qualifiers from pointer target type note: expected 'struct mystruct *' but argument is of type 'const struct mystruct *' 

This is really a warning in C by default, but a bug in C ++. This way you will break C-based applications compiled with the -Werror option and C ++-based applications compiled using g ++.

0
source

All Articles