3

There are two source files, a.c and b.c. a.c:

int main(void)
{
    foo();
    return 0;
}

b.c:

#include <stdio.h>

static void bar(void)
{
    puts("Hola!");
}

extern void (*foo)(void) = bar;

Compile them together (cl a.c b.c), run the program, the program will crash. Why is that?

However, a declaration like extern void (*foo)(void); would solve the problem.

My environment is Windows MSVC:

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.

I guess it's because:

  1. Since foo is not declared, the compiler guesses that it's a function.
  2. However, foo is not a function, but a variable, so the calling fails.
user26742873
  • 919
  • 6
  • 21

1 Answers1

3

Since foo is not declared, the compiler guesses that it's a function. However, foo is not a function, but a variable, so the calling fails.

Before C99 (request for a check), C does not force the user to declare functions before calling them, so there are no warnings or errors from the compiler; What's more, there is really one foo defined, no matter it is a variable or a function, so there are no warnings or errors from the linker. These make this issue hard to find.

However, as found in this SO post, sometimes an implicit function call like this would become a undefined behaviour (UB):

J.2 Undefined behavior

— For call to a function without a function prototype in scope where the function is defined with a function prototype, either the prototype ends with an ellipsis or the types of the arguments after promotion are not compatible with the types of the parameters (6.5.2.2).

user26742873
  • 919
  • 6
  • 21
  • 1
    “C does not force the user to declare functions before calling them” — Actually it totally does, unless you are using a woefully outdated version of C. The problem is that *implementations* aren’t always great at following the C standard in this regard. – Konrad Rudolph Sep 05 '20 at 17:48
  • @KonradRudolph Thank you for pointing out this, you remind me. After C99 there is a restriction, and I'm using MSVC 1998 (like c89). – user26742873 Sep 05 '20 at 17:49
  • @KonradRudolph C is what gets implemented, not what the standard says. As long as implicit function declarations are part of the language accepted in the default compilation mode by all widely used C compilers, they are a feature of C. Telling people they aren't only causes confusion. – zwol Sep 05 '20 at 17:55
  • 1
    @zwol I’m sympathetic regarding the confusion but I’m adamant that “C” is the *standard*. The implementations aren’t C, they’re *implementations of the standard*. This matters, because the standard is normative, the implementations aren’t. In particular, when there’s disagreement then the defect is *in the implementation*, and needs to be fixed *there*. This would matter less (or more?) if there was only one major implementation … but this isn’t the case. – Konrad Rudolph Sep 05 '20 at 17:58
  • @KonradRudolph That's a fine tack to take when filing bug reports on compilers, but that's not what we're doing here. When teaching C to beginners, which *is* what we're doing here — no language-lawyer tag on this question — you gotta take a more pragmatic view. – zwol Sep 05 '20 at 18:12
  • @zwol I totally agree with being pragmatic. But in the case of C this means teaching the rules, the actual behaviour, and about diagnostics (`-pedantic`, `-Wall` etc.). – Konrad Rudolph Sep 05 '20 at 18:45