为什么strlen函数在没有#include <string.h>的情况下工作?</string.h>

时间:2011-04-27 14:41:09

标签: c libraries std strlen string.h

快速提问:

无论我是strlen[char*]还是

#include <string.h>都能完美运作

我从编译器获得的所有内容都是关于隐式声明的警告,但在功能上它可以按预期工作。

为什么?

7 个答案:

答案 0 :(得分:6)

当您调用未定义的行为时,一种可能的行为是程序的行为与您预期的一样,一个系统当前版本< / em>已安装的库和系统软件。这并不意味着可以这样做。实际上正确的C99编译器不应该允许隐式函数声明;它应该给你一个错误。

答案 1 :(得分:4)

C中的函数原型是not compulsory。它们是编译器的有用指示,因此它可以对传入它们的类型进行类型检查。如果不包含string.h,则假定该函数使用默认签名,这就是您收到警告的原因。

答案 2 :(得分:3)

如果在范围内没有原型的情况下调用函数,编译器将生成代码以调用函数,该函数接受传递的任何类型的参数并接受整数结果。如果参数与函数期望的参数匹配,并且函数以调用代码可以处理(*)的方式返回其结果,那么一切都会很好。原型设计的目的是确保在可能的情况下将参数转换为期望的类型,并且如果无法转换,编译将失败。例如,如果非原型函数需要类型为“long”的参数,并且有人试图传递“int”,则可能发生以下任何一种情况:

  1. 程序可能会彻底崩溃
  2. 事情可能会按预期发挥作用
  3. 该函数可以像传递一些任意不同的参数值一样执行
  4. 程序可能会继续运行,但任意值都会破坏任何或所有程序变量。
  5. 计算机可能会导致恶魔飞出程序员的鼻子

相比之下,如果函数是原型,编译器将保证在调用函数之前执行将'int'转换为'long'所需的任何操作。

当最初设想C时,原型不存在,程序员负责确保所有参数都以预期的精确类型传递。在实践中,确保所有函数参数始终是完全正确的类型是非常痛苦的(例如,当将值5传递给期望长的函数时,必须将其写为“5L”或“(long)5”) )。实际上,除了可变函数之外,从来没有(**)任何理由依赖隐式参数类型。

(*)不正确的参数类型可能发生的任何事情都可能发生在不正确的返回类型中,除非函数需要返回'int'并且函数的实际返回值适合'int' ,与使用不正确的参数类型相比,结果更可能是正确的。

(**)我能想到的唯一例外是,如果一个人正在为一些原型感知编译器不可用的旧硬件编程,或者如果一个人正在编写代码高尔夫或类似的竞争对手。后者我考虑解谜而不是编程,而且我不知道任何有兴趣使用前者条件的硬件。

答案 3 :(得分:1)

因为它的声明即等于所谓的'默认声明'。编译器期望任何未知函数返回int并期望在代码中第一次使用函数时传递的参数。

答案 4 :(得分:1)

通常这是因为您包含的另一个头文件包括string.h。显然,假设你不需要仅仅因为其他事情而包含某些东西是不好的做法,但它很可能是造成这种影响的原因。

答案 5 :(得分:0)

我猜它是因为在C中int是从函数返回的默认数据类型。 你能举出更全面的代码示例吗?

答案 6 :(得分:0)

函数原型包含在包含文件中。因此,即使您不包含这些文件,也会编写固定原型int function_name();。现在strlen()的代码存在于运行时链接的库文件中,因此该函数提供了正确的输出(仅当它是唯一具有固定原型int function_name();的函数时)。