简体   繁体   English

为什么strcpy()在不包含的情况下工作<string.h>

[英]Why strcpy() is working without including <string.h>

I am working with some C example, and using function strcpy() , but forgot to include <string.h> , though I have included <stdio.h> . 我正在使用一些C示例,并使用功能strcpy() ,但是忘记了包含<string.h> ,尽管我已经包含了<stdio.h> To my surprise code ran successfully. 令我惊讶的是,代码成功运行了。 Following is the code I am executing: 以下是我正在执行的代码:

#include <stdio.h>

int main() {
   char message[10];
   int count, i;

   strcpy(message, "Hello, world!");

   printf("Repeat how many times? ");
   scanf("%d", &count);

   for(i=0; i < count; i++) {
      printf("%3d - %s\n", i, message);
   }
}

I am using gcc version 3.3.6 (Ubuntu 1:3.3.6 - 15ubuntu1) 我正在使用gcc version 3.3.6 (Ubuntu 1:3.3.6 - 15ubuntu1)

I even have not received any compilation warnings. 我什至没有收到任何编译警告。

在此处输入图片说明

Why my code is working without including <string.h> ? 为什么我的代码在不包含<string.h>情况下<string.h>正常工作?

Thanks in advance. 提前致谢。

The compiler assumes int strcpy() and invokes ancient backwards compatibility behavior. 编译器采用int strcpy()并调用古老的向后兼容行为。 Pointer arguments are one of the types for which this works so it's fine. 指针参数是可以工作的类型之一,所以很好。

Don't depend on it. 不要依赖它。 The safety rails are off. 安全导轨已关闭。

As I recall, GCC 3 defaulted to C89 conformance plus GNU extensions. 我记得,GCC 3默认为C89一致性以及GNU扩展。 C89 permitted functions to be called without previously having been declared -- they were assumed to return int , and their parameter types were inferred from the argument types. C89允许在不事先声明的情况下调用函数-假定它们返回int ,并且从参数类型推断出它们的参数类型。 If the resulting implicit type happened to match the called function's actual type (which was more likely in legacy C code than it is in modern code) then all was good. 如果结果隐式类型恰好与被调用函数的实际类型相匹配(在旧版C代码中比在现代代码中更有可能),那么一切都很好。 If not, then the behavior was undefined, but anything can happen with undefined behavior, even what the programmer who wrote the code expected to happen. 如果不是这样,则该行为是不确定的,但是任何未定义的行为都可能发生,甚至是编写代码的程序员所期望发生的一切。

Additionally, although the standards don't specify that any of the standard headers include other headers, they are not forbidden from doing so, and in practice, in some C implementations, some of them do. 此外,尽管标准未指定任何标准标头包含其他标头,但并不禁止这样做,并且实际上,在某些C实现中,其中一些标头也是如此。 If it happens that your implementation's stdio.h includes string.h or otherwise provides a compatible definition for strcpy() , then that serves just fine with that implementation . 如果您的实现的stdio.h包含string.h或以其他方式为strcpy()提供了兼容的定义,那么该实现就可以 If that's what you're relying on, however, whether intentionally or not, then you are at risk of unexpected failure when you try to use your program with a different implementation. 但是,如果这是您所依赖的,则无论您是否有意依赖,那么当您尝试将程序与其他实现一起使用时,您就有发生意外失败的风险。

Finally, do note that GCC 3.3 is very old. 最后,请注意GCC 3.3的版本旧。 If at all possible, you should upgrade to something newer. 如果有可能,您应该升级到较新的版本。 Even the stodgy, long-term stability Linuxes tend to be using at least versions late in the 4.x series, and the latest is GCC 8.3. 即使是不稳定的,长期稳定的Linux也倾向于至少在4.x系列中使用较晚的版本,而最新的版本是GCC 8.3。

The string.h include file tells the compiler how strcpy() is defined by giving a declaration of the function, but it doesn't provide the function itself, which instead sits in a library and will be automatically linked with your program. string.h包含文件通过给出函数声明来告诉编译器如何定义strcpy() ,但它不提供函数本身,而是位于库中并自动与程序链接。

If the function has not been declared when it reaches it, then the compiler will assume a declaration, based on defaults and how you use the function. 如果函数在到达函数时尚未声明,则编译器将基于默认值和您使用函数的方式假定一个声明。

The compiler takes what you wrote, so the addresses of message and Hello, world! 编译器接受您编写的内容,因此messageHello, world!的地址Hello, world! and assumes the function to return an int . 并假设函数返回一个int You take risks by not telling the compiler how it has to compile the code thanks to the include . 由于include您不必告诉编译器如何编译代码就冒了风险。 The outcome is undefined behavior. 结果是不确定的行为。

By the way, Hello, world! 顺便问一下Hello, world! takes 14 characters, 13 + the trailing \\0 , which is 4 more than in your declaration of message . 占用14个字符,加13 +尾随\\0 ,比您的message声明多4个字符。 This is undefined behavior, as the extra 4 chars will be written where they're not supposed to. 这是未定义的行为,因为多余的4个字符将被写在不应包含的位置。 Seemingly working, crash... 似乎正在工作,当机...

You cannot rely on a program showing an expected result. 您不能依靠显示预期结果的程序。 This is undefined behavior. 这是未定义的行为。

Always compile with the warnings options, like -Wall , and consider fixing all warnings. 始终使用-Wall类的警告选项进行编译,并考虑修复所有警告。

The compiler knows some "built-in" functions ( printf() is another example for some compilers), and makes up for your mistake by providing it. 编译器知道一些“内置”函数( printf()是某些编译器的另一个示例),并通过提供它来弥补您的错误。 It is a bad habit to rely on this because even if your today's compiler does this, nothing guarantees you that another one will do the same, so the compiled code won't be predictable. 依靠它是一个坏习惯,因为即使您今天的编译器这样做,也不能保证您另一个编译器也会这样做,因此编译后的代码将不可预测。

Try compiling with -Wall -Wextra to make the compiler show more warnings, including the ones for your forgotten header : gcc -o input input.c -Wall -Wextra . 尝试使用-Wall -Wextra进行编译,以使编译器显示更多警告,包括您忘记的标头的警告: gcc -o input input.c -Wall -Wextra

Also see here : warning: incompatible implicit declaration of built-in function 'xyz' 另请参见此处: 警告:内置函数'xyz'的不兼容隐式声明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM