OpenGL включает директивы на OS X - PullRequest
3 голосов
/ 10 ноября 2008

Я немного запутался, почему этот код компилируется. Я опускаю "необходимые" #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 просто указывает компоновщику, где находится библиотека, но я думал, что мне все еще нужны заголовки?

Ответы [ 3 ]

5 голосов
/ 10 ноября 2008

glClearColor не является макросом, поэтому не требуется заголовки для его определения. Если вы добавляете предупреждения:

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

Тогда вы получите предупреждение о неявном объявлении glClearColor. Вы также не сможете использовать какие-либо макросы, так как компилятор выдаст ошибку, что они не определены. Поскольку символ glClearColor правильно разрешается компоновщиком, вы никогда не получите сообщение об ошибке.

Мне также кажется, что вам это могло показаться интересным, потому что вы думали, что компилируете для C ++. Пример, который вы привели, на самом деле компилирует код на Си, где не является ошибкой провал объявлять прототипы функций. Если вы хотите скомпилировать это как код C ++, вам понадобится следующая командная строка:

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

В этом случае вы наверняка получите сообщение об ошибке, не включив gl.h, и ваш код не сможет скомпилироваться. При выполнении GCC из командной строки g ++ является компилятором C ++, а gcc - общим компилятором C.

3 голосов
/ 10 ноября 2008

В 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 functions, например prinft, или функциям, не имеющим прототипа (например, void f(), где нет информации о типах параметров и числе). Это причина того, что вам всегда нужно обращаться к переменным аргументам с va_arg, используя их продвинутый тип. GCC предупредит вас, если вы этого не сделаете.

Всегда включайте правильные заголовочные файлы, чтобы не сталкиваться с этими проблемами.

Редактировать: спасибо Крису за то, что он указал, что char literals (как 'a') всегда имеет тип int в C

0 голосов
/ 10 ноября 2008

Это на самом деле относится к классическому фрагменту C & R hello world:
http://en.wikipedia.org/wiki/Hello_world#History

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...