tags:

views:

821

answers:

3

I am a bit confused why this code compiles. I leave out the "necessary" #include <OpenGL/gl.h> and still the program can compile. How is this possible when my program is calling functions from the GL library, without including them.

int main(int argc, char** argv)
{

    glClearColor(1.0,1.0,1.0,1.0);
    return 0;
}

I use this compilation command:

 gcc -framework GLUT -framework OpenGL test.c

I was under the assumption that adding -framework just specifies to the linker where the library is, but I thought I still need the headers?

+4  A: 

glClearColor isn't a macro so you don't need the headers to define it. If you add warnings:

gcc -o test -Wall -W test.c -framework GLUT -framework OpenGL

Then you'll get a warning about the implicit declaration of glClearColor. You also won't be able to use any macros as the compiler will give you an error that they are undefined. Since the glClearColor symbol gets properly resolved by the linker, you never get an error.

It also occurs to me that you might have been wondering this because you thought you were compiling for C++. The example you gave actually compiles C code where it is not an error to fail to declare function prototypes. If you meant to compile this as C++ code, you would need the following command line:

g++ -o test test.cpp -framework OpenGL

In that case you most certainly would get an error for not including gl.h and your code would fail to compile. When executing GCC from the command line, g++ is the C++ compiler while gcc is the general C compiler.

Jason Coco
+3  A: 

In C (prior to C99), you don't have to declare functions in order to use them. The compiler will assume the function takes the promoted parameter types you pass to it, and assume the function returns an int. This, however can be quite problematic, and behavior is undefined if the function doesn't. Let's look at this:

/* file1.c */
void foo(char a, char b) {
    /* doing something ... */
}

/* main.c */
int main(void) {
    char a = 'a', b = 'b';
    /* char variables are promoted to int 
       before being passed */
    foo(b, a); 
}

Because the types are being promoted (char -> int, float -> double) if there is no declaration of the function at the time you call it, the arguments could not be passed at the right places in memory anymore. Accessing b can yield to a curious value of the parameter. As a side node, the same problem occurs when you pass arguments to vararg functions like prinft, or functions having no prototype (like void f(), where there is no information about the parameters types and count). This is the reason that you always have to access variadic arguments with va_arg using their promoted type. GCC will warn you if you don't.

Always include the proper header files, so you don't run into this problems.

Edit: thanks to Chris for pointing out that char literals (like 'a') are always of type int in C

Johannes Schaub - litb
'a' is not promoted to an int. it *is* an int. In C, character literals are ints.
Chris Young
i haven't known that. thanks for pointing that out.
Johannes Schaub - litb
they're actually ints, but according to the C99 standard, they can only contain values representable by an unsigned char. If they contain multi-byte escape sequences, characters or something outside unsigned char, they are then "implementation defined"
Jason Coco
A: 

This actually relates to the classic C&R hello world snippet:
http://en.wikipedia.org/wiki/Hello_world#History

shoosh