#include<stdio.h>
int main()
{
char a[5]="hello";
puts(a); //prints hello
}
为什么代码编译正确?我们需要六个地点来存储"hello"
,对吗?
答案 0 :(得分:9)
C编译器将允许您运行数组的末尾,它不会检查那种类型。
答案 1 :(得分:8)
C编译器允许您显式请求no null终止符。
char a[] = "Hello"; /* adds a terminator implicitly */
char a[6] = "Hello"; /* adds a terminator implicitly */
char a[5] = "Hello"; /* skips it */
任何小于5的值都会导致错误。
至于为什么 - 一种可能性是你的字符串是固定大小的,或者被用作字节值的缓冲区。在这些情况下,您不需要空终止符。
最佳做法是使用char a[]
,以便编译器可以自动将其设置为正确的值(包括终结符)。
答案 2 :(得分:2)
a
不包含空终止字符串(固定大小数组的额外初始值设定项 - 例如"hello"
中的空终止符 - 被丢弃),因此指向该数组的指针的行为是传递给puts
未定义。
答案 3 :(得分:2)
根据我的经验,很多编译器都会让你逃脱编译。但它通常会在运行时崩溃(因为你没有空终结符)。
答案 4 :(得分:1)
C char数组初始化包括仅在有空间或未指定数组维度时终止null。
答案 5 :(得分:0)
您需要6个字符来存储“hello”作为空终止字符串。但是char数组不限于存储nul终止的字符串,你可能需要将数组用于其他目的,并且在这些情况下强制使用额外的nul字符将毫无意义。
答案 6 :(得分:0)
那是因为在C内存管理是手动完成的,不像java和其他几种语言.... 在编译期间不会检查您分配的六个位置但是如果您 必须进入归档(我的意思是实际存储)你将遇到运行时错误,因为程序在内存中保留了五个位置(但预计会保留六个),但编译器没有检查!
答案 7 :(得分:-1)
“hello”字符串保存在只读存储器中,最后为0。 “a”指向此字符串,这就是程序可以正常工作的原因。但我认为通常这是未定义的行为。 有必要查看编译器生成的汇编代码,看看究竟发生了什么。如果你想在这种情况下获得垃圾输出,请尝试:
char a[5] = {'h', 'e', 'l', 'l', 'o'}
答案 8 :(得分:-1)
您正在使用的C编译器不检查字符串文字是否适合char数组。由于文字包含终止零,因此数组中需要6个字符以适合文字“Hello”。现代编译器,例如Visual C ++ 2010,会检查这些内容并为您提供错误。