C/C++ определения функций

Вчера я наблюдал здесь дискуссию о компиляторах и компоновщиках. Речь шла об определениях функций библиотеки C. Я никогда не думал об этом, поэтому это вдохновило меня на поиски, но я не могу найти именно то, что хочу. Интересно, какой наименьший синтаксис вам нужно добавить в исходный код, чтобы включить только функцию printf(). Я имею в виду объявление функции из stdio.h, которое вам нужно.


person Vit    schedule 15.03.2010    source источник
comment
Почему вы хотите этого? Какую пользу дает вам кратчайший путь? В частности, для printf ваша библиотека может быть (немного) более подробной, чтобы пометить функцию как требующую проверки спецификаторов формата (например, gcc делает это с включенным -Wformat). Сообщив нам, почему вы не хотите включать ‹stdio.h›, вы могли бы предложить лучшее решение.   -  person    schedule 15.03.2010
comment
Это просто, я просто хочу лучше понять путь от printf() к реальному коду. Есть ли хорошие статьи в Интернете? Потому что многие книги недоступны в моей стране.   -  person Vit    schedule 15.03.2010
comment
Вы хотите написать свою собственную функцию, назовем ее my_printf, которая ведет себя так же, как стандартная printf?   -  person    schedule 15.03.2010
comment
Да, это именно то, что я хочу. Мне не нужно, чтобы он был таким же сложным, как printf(), просто чтобы вывести на стандартный вывод простую строку.   -  person Vit    schedule 16.03.2010


Ответы (3)


Объявление C99 printf() является

int printf(const char *restrict, ...);

но большинство компиляторов также примут

int printf(const char *, ...);    

См. также C99, раздел 7.1.4, §2:

При условии, что библиотечная функция может быть объявлена ​​без ссылки на какой-либо тип, определенный в заголовке, также допустимо объявлять функцию и использовать ее без включения связанного с ней заголовка.

Примечание. В этом случае квалификатор restrict в сочетании с const обещает компилятору, что строка формата никогда не будет изменена в пределах printf(), даже если указатель снова передается как один из аргументов с переменным числом переменных.

person Christoph    schedule 15.03.2010
comment
@David: restrict - это не имя аргумента, а один из трех квалификаторов типа C99 (остальные - const и volatile) - person Christoph; 15.03.2010
comment
@Christoph: На самом деле restrict означает, что компилятор может игнорировать псевдонимы, и вы не можете снова передать строку формата в качестве аргумента с переменным числом аргументов. Если вы передадите его дважды, это поведение undefined; см. 6.7.3.1/4 стандарта C. - person ; 15.03.2010
comment
@Roger: я тоже так думал (проверьте мои правки в ответе), но это неправильно: 6.7.3.1, пример 3 явно показывает, что два аргумента restrict могут ссылаться друг на друга, пока объект, на который указывает, не изменяется в пределах функция, которую printf() не делает, т.е. printf(foo, foo) должна быть легальной!; вы не можете видеть только из объявления, разрешено ли передавать указатели с псевдонимами - person Christoph; 15.03.2010
comment
@Christoph: Я на самом деле расшифровал (или думал, что сделал) /4, чтобы перепроверить перед публикацией, но тогда вам пришлось пойти и испортить его простым примером. - person ; 15.03.2010
comment
@Roger: причина этого несколько запутанного определения заключается в том, что restrict существует не для того, чтобы давать обещания вызывающему (как это сделал бы const), а для того, чтобы обеспечить дальнейшую оптимизацию внутри вызываемого< /я> ; только когда вы комбинируете эти квалификаторы (например, const *restrict), вы можете вывести дополнительную информацию только из объявления - person Christoph; 15.03.2010

Определение обычно компилируется в общей библиотеке. Декларация - это то, что вам нужно. Отсутствие объявления в области действия вызывает неопределенное поведение. Итак, для каждой библиотеки у вас обычно есть (набор) заголовочных файлов и скомпилированная двоичная общая/статическая библиотека. Вы компилируете свои исходники, включая соответствующие заголовки и ссылку на библиотеку. Чтобы ввести объявление в область действия, используйте директиву #include. Например. для printf вы бы сделали:

#include <stdio.h>
int main() {
    printf("Hello, world\n");
    return 0;
}

Но тогда любая приличная книга по C или C++ уже должна освещать это подробно и с лучшими примерами.

person dirkgently    schedule 15.03.2010
comment
Есть ли способ увидеть фактические определения этих функций? В коде C или ASM? - person Vit; 15.03.2010

Это зависит от вашего компилятора и платформы.

В большинстве случаев просто объявляя

int printf(const char *, ...);

Однако ваш конкретный компилятор/платформа или реализация библиотеки C даже могут изменить это объявление для целей соглашения о вызовах.

В общем, не стоит пытаться объявлять вещи самостоятельно, так как это может быть нарушением правила одного определения. В этом случае вы всегда должны включать соответствующий заголовок, stdio.h(cstdio для C++).

person Ramon Zarazua B.    schedule 15.03.2010