...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <string.h> char *(*fp)(const char *, int); int main(void) { const char *c; fp = strchr; c = fp("Hello",'e'); printf("%s\n", c); return 0; } |
Noncompliant Code Example
In this noncompliant example, the function buginf()
is defined to take a variable number of arguments and expects them all to be signed integers, with a sentinel value of -1
:
Code Block | ||||
---|---|---|---|---|
| ||||
/* In another source file */
void buginf(const char *fmt, ...) {
/* ... */
}
/* In this source file, no buginf prototype in scope */
void buginf();
void h(void) {
buginf("bug in function %s, line %d\n", "h", __LINE__);
} |
While this code appears to be well-defined due to the prototype-less declaration of buginf()
,this code exhibits undefined behavior per subclause 6.7.6.3 paragraph 15 [ISO/IEC 9899:2011]:
For two function types to be compatible, both shall specify compatible return types.146) Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types. If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the parameter list shall not have an ellipsis terminator and the type of each parameter shall be compatible with the type that results from the application of the default argument promotions.
Compliant Solution
In this compliant solution, the prototype for the function buginf()
is included in the scope in the source file where it is used:
Code Block | ||||
---|---|---|---|---|
| ||||
/* In another source file */
void buginf(const char *fmt, ...) {
/* ... */
}
/* buginf prototype in scope in this source file */
void buginf(const char *fmt, ...);
void h(void) {
buginf("bug in function %s, line %d\n", "h", __LINE__);
/* ... */
}
|
Noncompliant Code Example
In this noncompliant example, the function f()
is defined to take an argument of type long
, but f()
is called from another file with an argument of type int
:
Code Block | ||||
---|---|---|---|---|
| ||||
/* In another source file */ long f(long x) { return x < 0 ? -x : x; } /* In this source file, no f prototype in scope */ long f(); long g(int x) { return f(x); } |
Compliant Solution
In this compliant solution, the prototype for the function f()
is included in the scope in the source file where it is used, and the function f()
is correctly called with an argument of type long
:
...