我写了两个版本的代码来练习如何制作字符数组,我希望结果是一样的。
版本1:
int main(void)
{
char a[7] = "and";
printf("size: %d length: %d",sizeof(a), strlen(a) );
}
版本2:
int main(void)
{
char a[7];
a[1] = 'a';
a[2] = 'n';
a[3] = 'd';
printf("size: %d length: %d",sizeof(a), strlen(a) );
}
然而,我得到的结果是:
版本1:
size: 7 length: 3
版本2:
size: 7 length: 4
据我所知,字符串以null字符结尾,字符串文字中的null字符是隐含的,但为什么它会消失呢?为什么它没有作为最后一个元素包括在内,因为版本1中的长度显示为3?
实际上strlen
应该排除空字符,所以输出3
是正确的。第二个版本的问题是a[7]没有初始化,因此它的值可能是任意的。在这种情况下,第5个值为0,而第0个值不为0,因此输出为4。请注意,在第二个版本中,您使用了错误的索引——数组的索引从0开始,而不是从1开始。
如果你想在第二个版本中实现这一点,请这样重写:
int main(void)
{
char a[7] = {0};
a[0] = 'a';
a[1] = 'n';
a[2] = 'd';
printf("size: %d length: %d",sizeof(a), strlen(a) );
}
这将显式地将a中的第一个值初始化为0,并隐式地使所有其他值也为零。
在第二种情况下
int main(void)
{
char a[7];
a[1] = 'a';
a[2] = 'n';
a[3] = 'd';
printf("size: %d length: %d",sizeof(a), strlen(a) );
}
你很幸运
a[0]
不包含0
(即' '
或null(:您会看到值0
作为长度a[4]
实际上有一个空值,否则,您的计算机可能已经被烧毁
换句话说,对于具有自动存储的局部变量,如果未初始化,则值是不确定的。不能保证0填充(充当null终止符(,因此将数组用作字符串(例如:strlen()
的参数(可能会访问超出绑定的内存并调用未定义的行为。
sizeof
测量某个事物的内存大小。strlen
计算c字符串的长度(长度定义为字符序列的长度,不包括以nul结尾的字符(。这里你的c字符串比用来存储它的内存短。
sizeof
是作为编译时计算的C运算符。
strlen
是一个库函数,在运行时调用。
strlen(3)
描述strlen((函数计算字符串s的长度。
RETURN VALUESstrlen((函数返回终止NUL字符。
请注意,第二个示例未定义,因为字符数组未初始化,strlen
可能溢出。。。您不能保证未初始化的字符设置为0。
根据strlen
描述:
size_t strlen(const char *str);
返回给定以null结尾的字节字符串的长度,即
str
指向其第一个元素的字符数组中的字符数,最多不包括第一个null字符。如果str
不是指向以null结尾的字节字符串的指针,则行为未定义。
由于在第二个版本中,a
不是以null结尾的字节字符串,因此行为未定义。
请注意,将单个字符文字分配给char
数组并不会使其成为字符串文字,要使用这种分配创建一个以null结尾的char
数组,您需要自己完成,从索引0
:开始
a[0] = 'a';
//...
a[3] = ' ';