C语言有内置函数吗?

4

Python内置了大约50个函数。C语言的printfscanf函数属于stdio.h库。

C语言本身是否有任何函数?


C 标准库是 C 语言的一部分。ISO 9899 标准不可免费获取,但草案是可以自由获取的,请参见 http://www.open-std.org/jtc1/sc22/wg14/www/projects。 - user13963867
1
如何定义“内置函数”?如果您不想包括 stdio.h,则可以自由声明 printfscanf。在 C89 中,您甚至不需要声明它们。 - interjay
有编译器内嵌函数,它们通常与CPU指令一一对应,但这些都是编译器和CPU特定的,没有标准化。 - Shawn
预处理阶段是否包括defined,或者sizeof_Alignof计算?也许是_Generic?这些都是“表达式”,它取决于您如何定义“内置函数”。 - KamilCuk
@Brendan 标准规定 sizeof 和类似的不是函数。sizeof_Alignof_Pragma 是运算符,而 _Static_assert 则是声明。 - user694733
显示剩余2条评论
3个回答

4

C语言只有很少的关键字,但没有内置函数。每个你使用的函数都来自于其他库。即使没有标准库,也可以通过-nostdlib标志(对于gcc)编译程序。


1
所有的C标准库函数都内置于语言中——它们是C标准定义的一部分。C实现(特别是编译器)可以将这些函数实现为编译器实现的内置函数或链接器链接的目标模块。C标准在很大程度上将规定C程序必须如何行事的规则与关于C程序必须如何实现的规则分开。就C程序的行为方式而言,内置函数和链接函数之间没有区别:函数的行为相同,没有办法描述两种实现之间的可观察差异。编译器通常使用内置实现和链接实现的混合。例如,在void foo(uint32_t u) { float f; memcpy(&f, &u, sizeof f); … }中,编译器可能通过生成指令从整数寄存器移动数据到浮点寄存器来实现memcpy,而不是调用任何外部的memcpy例程。对于其他的memcpy调用,它可能生成简单的指令来移动字节,并且不再调用外部例程。对于sqrt,如果目标机器具有适当的平方根指令,它可能会生成一个平方根指令。
更为复杂的函数通常通过调用编译后链接到程序中的外部函数来实现。即使有许多这样的函数,编译器也可能识别特殊情况并提供对替代函数的调用(printf("Hello, world.\n") 可以被实现为 puts("Hello, world."),执行函数而无需调用的指令(pow(x, 2) 可以被实现为将 x 乘以自身),或者结果可以通过内置于编译器的代码在编译时计算(sin(.3) 可能会在编译时计算)。

虽然我不反对这些观点,但是C程序员使用printf()和Java程序员使用System.out.println()的方式之间仍存在根本性的差异。在许多环境中,C实现可能没有printf()甚至没有malloc();但是Java JVM没有System.out是不可想象的。C编译器可以与特定的标准库分离,在嵌入式系统中具有非常重要的意义。 - Kevin Boone

1
这取决于你所说的“语言的一部分”是什么意思。有规范定义了C标准库应该提供什么,因此printf()等都是“语言的一部分”。然而,C编译器不会生成实现这些函数的代码--它们应该以某种库的形式提供。大多数C编译器都知道库在哪里/是什么,并配置为自动链接它。如果您不想使用标准库,您几乎肯定可以告诉编译器/链接器不要这样做。有时候这样做是有好处的。
尽管有一个标准库的规范,但语言语法本身与库几乎没有耦合。例如,在Java中,如果您添加一个String和一个对象,编译器将生成调用对象的toString()方法的代码。这个方法必须存在,因为Java语言和Java运行时库是密切相关的。
在C中,没有真正等效于这个过程--C编译器可以完全不知道可能可用的函数而生成代码。这些函数需要在运行时之前提供,但这实际上是链接器的工作,而不是编译器的工作。
然而,gcc 至少有一个“内置”函数的概念。例如,如果我尝试编译这个代码:
void printf (void)
  {
  }

我收到一个警告:

test.c:1:6: warning: conflicting types for built-in function 
‘printf’; expected ‘int(const char *, ...)’ [-Wbuiltin-
 declaration-mismatch]

即使我使用-nostdlib开关,gcc仍然认为printf()是“内置的”,尽管它不会为其生成代码。
我想这种“内置函数”的概念并不完全明确。

然而,“C编译器不会生成实现这些函数的代码”是不正确的。编译器确实会生成这样的代码。例如,memcpysqrt通常会被替换为内联代码。 - Eric Postpischil
好的,说得有道理。我承认编译器可能会为能够内联的函数生成代码。这些函数大概只占所有函数的一个相对较小的子集。 - Kevin Boone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接