我遇到了问题的一部分,其中我得到了输出,但我需要解释为什么它是真的并且有效?
char arr[4];
strcpy(arr,"This is a link");
printf("%s",arr);
当我编译并执行时,我得到以下输出。 输出:
This is a link
最佳答案
为什么它(当时)有效的简短答案是——你很幸运。超出数组末尾的写入是未定义的行为。 未定义的行为就是未定义,它很容易导致段错误,因为它确实产生了输出。 (尽管通常,结果是堆栈损坏)
在 C 中处理字符数组时,您有责任确保分配了足够的存储空间。当您打算将数组用作字符串时,还必须为每个字符分配足够的存储空间 +1
结尾处的 nul 终止 字符(这是 C 中 nul 终止 字符串的定义)。
为什么它有效?一般来说,当您请求时说 char arr[4];
编译器仅保证为 arr
分配了 4 个字节。但是,根据编译器、对齐方式等,编译器实际上可能会将其用作最小分配单元的任何内容分配给 arr
。这意味着虽然您只请求了 4-bytes
并且只保证有4-usable-bytes
,编译器实际上可能已经预留了 8, 16, 32, 64, or 128, etc-bytes
.
或者,再说一次,你只是幸运 arr
是最后一次请求的分配,并且尚未请求或写入从 byte-5
开始的内存地址。关注arr
内存中。
重点是,您请求 4-bytes
并且只保证有4-bytes
可用的。是的,它可能适用于那个printf
在代码中发生任何其他事情之前,但是您的代码完全不可靠,并且您正在玩带有堆栈损坏的俄罗斯轮盘赌(如果尚未发生)。
在 C 语言中,您有责任确保您的代码、存储和内存使用都明确定义,并且您不会陷入未定义的领域>,因为如果你这样做,所有的赌注都会被取消,并且你的代码不值得它存储的字节。
如何使代码定义良好?适当限制和验证代码中的每个必需步骤。对于您的代码片段,您可以使用 strncpy
而不是strcpy
然后肯定nul-terminate arr
在调用printf
之前,例如
char arr[4] = ""; /* initialize all values */
strncpy(arr,"This is a link", sizeof arr); /* limit copy to bytes available */
arr[sizeof arr - 1] = 0; /* affirmatively nul-terminate */
printf ("%s\n",arr);
现在,您可以信赖 arr
的内容贯穿代码的其余部分。
关于C 中的 Char 和 strcpy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37382384/