user3284469
user3284469

Reputation:

How are we allowed to use a forward-declared object or function, and how are we not?

If we declare an object or function without defining it, how are we allowed to use it before its declaration and how are we not allowed to use it before its declaration ? (For a similar question using a forwarded declared structure tag before its definition, basically how we are allowed to use an incomplete type and how not, see https://stackoverflow.com/a/45725061/3284469)

Does it matter if the declaration appears in file scope or block scope?

Does it matter if its definition appears in the same or a different translation unit?

For example

extern int i;

(what can we do with i here?)
(what can't we do with i here?)
int A = i+3; // error: initializer element is not constant. This is an error not due to forward declaration of int i

int i = 3;


void fun();

(what can we do with fun here?)
(what can't we do with fun here?)

void fun(){};

Upvotes: 7

Views: 112

Answers (4)

haccks
haccks

Reputation: 106092

what can we do with i here

With

extern int i; 
  1. i can be declared as many times as required in the program.
  2. You can have an initializer

    extern int i = 0;    
    

what can't we do with i here?

You can't use i without defining it in the program.

extern int i;
int main(void)
{
    i = 10;    // Will through an error
    return 0;
}

In case of function this keyword only tells that the linkage for the function is extern. By default linkage of a function declaration/definition is extern.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726809

Declaring an object is a promise to provide a definition at some other place. Once you declare a function or an external variable, from that point on you are allowed to do anything that you would be allowed to do to a function or a variable that you have defined.

The scope of the declaration has no effect on what you can do, only on the location in code where you can do it.

In most cases, code translator requires all external references to be satisfied at the time the code is linked. Otherwise, you get a linking error.

One exception to this rule is using declared object in a sizeof expression, which does not require an access to underlying object:

extern int undefined;
size_t res = sizeof(undefined);

The above will not break a link, because sizeof expression does not generate access to its arguments.

Upvotes: 4

msc
msc

Reputation: 34638

www.cprogramming.com say's:

When you declare a variable, a function, or even a class all you are doing is saying: there is something with this name, and it has this type. The compiler can then handle most (but not all) uses of that name without needing the full definition of that name. Declaring a value--without defining it--allows you to write code that the compiler can understand without having to put all of the details. This is particularly useful if you are working with multiple source files, and you need to use a function in multiple files. You don't want to put the body of the function in multiple files, but you do need to provide a declaration for it.

extern int i;

Here, an integer type variable i has been declared (but no definition i.e. no memory allocation for variable i so far). And we can do this declaration as many times as needed.

void fun();

Function fun() declare, but not defined. but it does tell the compiler that it can use this function and expect that it will be defined somewhere.

Upvotes: 0

John Zwinck
John Zwinck

Reputation: 249394

You can do anything with the declaration except for inlining it. For example:

void fun();
inline void fun(){}

After the declaration you can call the function, unless the definition is marked inline in which case it will result in a linker error because the definition does not emit a symbol to link against. Even if you don't say inline explicitly, an optimizing compiler may inline calls to the function if the definition has been seen.

Upvotes: 0

Related Questions