2010-03-15 51 views
2

昨天,我一直在关注编译器和链接器的讨论。这是关于C库函数的定义。我从来没有想过,所以它激励我去做一些搜索,但我找不到我想要的。我想知道,为了启用printf()函数,需要添加到源代码中的最小语法是什么。我的意思是你需要stdio.h的函数声明。功能的C/C++定义

+1

你为什么要这样?最短给你带来的好处是什么?特别是,对于* printf *,您的库可能(稍微)更加冗长,以将该函数标记为需要检查格式指示符的函数(例如,gcc通过启用“-Wformat”来执行此操作)。告诉我们为什么你不想包括可以让我们提供更好的解决方案。 – 2010-03-15 08:57:09

+0

这很简单,我只是想更好地理解从printf()到实际代码的方式。网上有没有好的文章?由于许多书籍在我的国家不可用。 – Vit

+0

你想写自己的函数吗,我们称之为'my_printf',其行为与标准'printf'相同? – 2010-03-15 11:32:38

回答

1

定义通常编译在共享库中。声明是你需要的。没有在范围内声明调用未定义的行为。因此,对于每个库,您通常都会有(一组)头文件和编译后的二进制共享/静态库。您可以通过添加适当的标题并链接库来编译源代码。要引入范围声明,请使用#include指令。例如。为printf你会怎么做:

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

但后来什么像样的书在C或C++应该已经对此进行了详细和更好的例子覆盖。

+0

有没有办法看到这些函数的实际定义?在C或ASM代码? – Vit

3

printf()的C99声明

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

但大多数编译器也将接受

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

参见C99 7.1.4节,§2:

只要有一个库函数可以在不参考 标题中定义的任何类型的情况下声明,它也是pe可以声明该功能并使用它,而不包括其关联的标头 。

注:在这种情况下,restrict预选赛const联合承诺,格式字符串我们从未在printf()修改编译器,即使指针再次通过为可变参数之一。

+2

@David:'restrict'不是参数名称,而是三个C99类型限定符之一(其他是'const'和'volatile') – Christoph

+1

我不知道,谢谢澄清。 –

+0

@Christoph:实际上,'restrict'意味着编译器可以忽略别名,并且*不能*再次传递格式字符串作为可变参数。如果你确实通过了两次,那是不确定的行为;见C标准中的6.7.3.1/4。 – 2010-03-15 08:39:43

0

这取决于你的编译器和平台。

在大多数情况下只是宣布

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

只会做,不过,你的特定的编译器/平台或C库实现,甚至可以更改此声明,对于调用约定用途。

总而言之,尝试自己声明事情并不值得,因为这可能违反了一个定义规则。在这种情况下,您应该始终包含适当的头文件stdio.h(C++的cstdio)。

+0

这只是为了学习目的... – Vit