3

Does the order in which C objects appear on the file matter?

For example, in functions, if I create two functions and the one above references the other one will it work? (Yes it will, I've tried it.) Is the same in effect for static functions, INLINE functions, etc.? Is the same in effect for structs? What happens if I reference a struct which is defined further down on the .c file?

Is this to any extend compiler-specific? How does the compiler work in this case? Does it first scan the whole file for all declarations/definitions and then attempts to dereference functions/symbols?

user794425
  • 39
  • 1
  • If you found an appropriate answer, you should check the "Accept" mark under its score: it means that the answer solved your problem. – zneak Jun 13 '11 at 04:06

4 Answers4

3

First, if by "if I create two functions and the one above references the other one will it work?" you mean something like this:

int foo()
{
    return bar();
}

int bar()
{
    return 0;
}

Then the compiler may do educated guesses at what bar() is, but it will at least spit a warning if bar() wasn't already declared. For symbols that can't be called (like variables or types), it's an outright error if they're used before they're declared.

In C, whenever you use an identifier (and no matter the kind of the identifier: it may be a function, a variable, a type, etc.), it should be declared beforehand. The various modifiers you may add to any identifier (like you said, static, inline and all the others) have no impact on this.

Do not confuse declaration and definition. A declaration is just telling the compiler that a name exists; a definition actually tells the compiler what it is.

For instance, this is a definition:

int bar() { return 4; }

Notice how it has a body, with (simple) code inside.

This is the matching declaration:

int bar();

The compiler will gladly accept the use of a function as soon as it sees either the declaration or the definition for it. For organization reasons and better flexibility, it's often better to write declarations for all your functions at the top of your C file (or inside an included header file) then the definitions.

So, my first example should look like this:

int foo();
int bar();

int foo()
{
    return bar();
}

int bar()
{
    return 0;
}

With the declarations above the C code, I can change the order of the functions in any way I like.

zneak
  • 134,922
  • 42
  • 253
  • 328
2

Typically something must be defined above where you use it. You can avoid this in different ways for different situations.

For functions, just provide a prototype above where it's called and all will be well.

int trol(int a, int b);

// use trol(int, int)

int trol(int a, int b) { }

If you have two functions, a and b, and they call each other and are defined in the order of: a, b, then you must provide b's prototype above the definition of a. a's prototype is not required because it is defined above where it is used inside b. Then the compiler will have no problems.

One other special case for functions is that you can use a function without declaring it and the compiler will try to infer the signature from the call. This answer explains it pretty well I think: Must declare function prototype in C?

For structs, you can use pointers to them before they are actually defined (but you can't access any of the fields) by providing a forward declaration:

struct s;

// use s*'s

struct s { };

(The above scenario facilitates recursive data structures like linked lists and trees; you can use pointers to structs before they are fully defined because the size of any type of pointer is constant.)

Community
  • 1
  • 1
Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • _Declared,_ not defined. Declaring is a statement that something exists (like a function prototype), defining is the act of, ... well, defining it (such as a function with body). – paxdiablo Jun 12 '11 at 02:23
  • @pax oops, I always get those two terms mixed up. fixed. – Seth Carnegie Jun 12 '11 at 02:29
1

It matters, because if the compiler doesn't know what the function is - it will try to 'guess' (create a default int foo() prototype with matching parameters), and if your call is incorrect - you'll have mismatches (build errors, implicit castings, whatever).

It is common practice (if not even required) to declare the function before calling it (through prototypes aka forward declarations).

For functions with variable parameter lists (like printf) you must have a forward declaration for them to work properly. For example this code will not compile:

int foo(int a)
{
    b(a);
    b("hello", "kitty");
}

void b(int a, ...)
{

    printf("%d", a);
}

But this - will:

#include <stdio.h>
int foo(int a)
{
    return b(a);
}

int b(int a)
{

    return printf("%d", a);
}

(with warning about the implicit forward declaration)

So in order to avoid dealing with the order of the objects in the file - use prototyping (forward declarations) to let the compiler know what's following.

littleadv
  • 20,100
  • 2
  • 36
  • 50
1

From my experience, everything in C has to be written with the referenced "object" before the reference is made. I don't think this is specific to any compiler, but maybe there are some which I haven't found. Basically, everything always has to be:

Object Declaration
...
Object Reference
Jon Egeland
  • 12,470
  • 8
  • 47
  • 62