cdeclarationmath.h

Implicit declaration of standard function in C


This question comes from an attempt to understand the "C philosophy" and not from any "real problem".

Suppose that in a C program I use sin(x):

#include <stdio.h>

int main() {
  char s[20] = "aha";
  printf("%f", sin(s));
  return 0;
}

I have deliberately made two mistakes:

  1. I have not #includeed math.h (or provided any declaration for sin).
  2. I made s of type char * (just something that cannot be cast meaningfully to a double).

I compile using GCC with the -lm flag.

As expected, I get one warning and one error.

Of course, there is the warning of implicit declaration of function blah blah:

bad.c: In function ‘main’:

bad.c:5:15: warning: implicit declaration of function ‘sin’ [-Wimplicit-function-declaration]
    5 |   printf("%f", sin(s));
      |                ^~~
bad.c:5:16: warning: incompatible implicit declaration of built-in function ‘sin’
bad.c:2:1: note: include ‘<math.h>’ or provide a declaration of ‘sin’
    1 | #include <stdio.h>
  +++ |+#include <math.h>

A little research seems to indicate that if a function is not declared beforehand, then C assumes a "default declaration" (the so called "implicit declaration") which is like int undeclaredfunction(void).

But I also get the following error:

    2 |
bad.c:5:19: error: incompatible type for argument 1 of ‘sin’
    5 |   printf("%f", sin(s));
      |                    ^
      |                    |
      |                    char *
bad.c:5:20: note: expected ‘double’ but argument is of type ‘char *’

This shows that the "implicit declaration" expects an argument of type double.

  1. It seems that C maintains a list of correct "implicit declarations" for "standard functions". Where can I find the comprehensive list of such correct implicit declarations for a given compiler (say gcc or clang)?
  2. If C already has the correct declarations of the standard math functions built in, then why does it expect the programmer to #include<math.h>? Just because of tradition? Or neatness?

The answer(s) that I looking for are about the exact rules used by the compiler, and not about subjective comments about "good programming practices".


Solution

  • The C standard gives little if any mention of built-in functions, however some C implementations have a set of built-in functions that are "predeclared", so to speak.

    For GCC in particular, the following page lists the built-in functions:

    7 Built-in functions provided by GCC

    And this page in particular lists C library functions that are built in:

    7.1 Builtins for C library functions

    The sin function is among this list, so the proper declaration of double sin(double) exists as a built-in.

    If this same code is compiled under MSVC, it does not generate an error. Their list of built-in functions can be found here:

    Compiler intrinsics

    And apparently sin is not among its list of built-in functions, so it uses the implicit declaration of int sin() (note that prior to C23 this is not the same as int sin(void), as the former has an unspecified number of arguments while the latter has zero). Subsequently running the program would trigger undefined behavior as the sin function is being called through an incompatible function pointer.