3

我有点困惑为什么这段代码可以编译。我省略了“必要的” #include <OpenGL/gl.h>,但程序仍然可以编译。当我的程序从 GL 库调用函数而不包括它们时,这怎么可能。

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

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

我使用这个编译命令:

 gcc -framework GLUT -framework OpenGL test.c

我假设添加 -framework 只是指定库所在的链接器,但我认为我仍然需要标头?

4

3 回答 3

5

glClearColor 不是宏,因此您不需要标题来定义它。如果添加警告:

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

然后你会收到关于 glClearColor 隐式声明的警告。您也将无法使用任何宏,因为编译器会给您一个错误,即它们未定义。由于链接器正确解析了 glClearColor 符号,因此您永远不会收到错误。

我还想到,您可能一直想知道这一点,因为您认为您正在为 C++ 进行编译。您给出的示例实际上编译了 C 代码,其中未能声明函数原型不是错误。如果您打算将其编译为 C++ 代码,则需要以下命令行:

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

在这种情况下,您肯定会因为不包含 gl.h 而收到错误,并且您的代码将无法编译。从命令行执行 GCC 时,g++ 是 C++ 编译器,而 gcc 是通用 C 编译器。

于 2008-11-10T06:48:49.773 回答
3

在 C(C99 之前)中,您不必为了使用它们而声明函数。编译器将假定该函数采用您传递给它的提升参数类型,并假定该函数返回一个int. 然而,这可能会产生很大的问题,如果函数没有,则行为是不确定的。让我们看看这个:

/* 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); 
}

因为如果在调用函数时没有声明函数,则类型会被提升(char -> int, float -> double),所以参数无法再在内存中的正确位置传递。访问 b 可能会产生一个奇怪的参数值。作为一个侧节点,当您将参数传递给vararg functionslikeprinft或没有原型的函数(like void f(),其中没有关于参数类型和计数的信息)时,也会出现同样的问题。这就是您始终必须va_arg使用其提升类型来访问可变参数的原因。如果你不这样做,GCC 会警告你。

始终包含正确的头文件,这样您就不会遇到这个问题。

编辑:感谢 Chris 指出char literals(like 'a') 始终是intC中的类型

于 2008-11-10T06:53:29.513 回答
0

这实际上与经典的 C&R hello world 片段有关:
http ://en.wikipedia.org/wiki/Hello_world#History

于 2008-11-10T08:28:58.090 回答