atomSmasher
atomSmasher

Reputation: 1465

Why do I need to declare this function extern. It works without it

I am new to the concept of extern. Today at work I came across a large number of extern functions that were declared inside of header file; foo.h. Somewhere off in a mess of folders I found a foo.c file that contained the definition of said functions but it did not #include foo.h. When I got home I decided to play around with the extern storage class examples. After doing some reading in the "C book" this is what I came up with.

Here is what I DID NOT expect to work. But it did.

main.c

#include <stdio.h> 

int data;

int main()
{

  data = 6;

  printf("%d\n", getData());

  data = 8;

  printf("%d\n", getData());
  return 0;
} 

externs.c

int getData()
{
  extern int data;
  return data;
}

bash

gcc main.c externs.c -o externs

I didn't think this would work because the function is not technically (or at least verbose) defined before main. Does this work because the default storage class for int getData() is extern? If so, why even bother with the following example (similar to what I saw at work)?

main2.c

#include <stdio.h> 
#include "externs.h"

int data;

int main()
{

  data = 6;

  printf("%d\n", getData());

  data = 8;

  printf("%d\n", getData());
  return 0;
} 

externs.h

#ifndef _EXTERNSH_
#define _EXTERNSH_

extern int getData();

#endif

externs.c

int getData()
{
  extern int data;
  return data;
}

bash

gcc main2.c externs.c -o externs

Upvotes: 3

Views: 120

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 753675

By default, GCC version 4.x or earlier compiles in a C89/C90 compatibility mode, which does not require functions to be declared before use. Undeclared functions are inferred to have a return type of int. By default, GCC 5.x or later compiles in C11 compatibility mode, which does require functions to be declared before use — as does C99.

Given that the code compiled without complaints, we can infer that you are using GCC 4.x.

Even so, you are not obliged to provide full prototypes, though you would be foolish not to. I routinely compile code with the options:

gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition -Wold-style-declaration …

I suspect that there is some redundancy in there, but those options catch many problems before I get around to running the code.

Upvotes: 4

M.M
M.M

Reputation: 141554

Functions are implicitly extern. You can change this by declaring them as static.

You are right that it is redundant to say extern int getData(); compared to int getData(); but some people feel that it improves code clarity.

Note that since C99, your first example is ill-formed. It calls getData without that function having been declared. In C89 this performed an implicit int getData(); declaration, but since C99 that was removed. Use the compiler switches -std=c99 -pedantic to test this.

Upvotes: 5

Related Questions