为什么此非空终止的字符串正确打印

Hem*_*mil 6 c string initialization c-strings

昨天,我进行了单元测试。程序之一是复制字符串并找出没有字符串功能的长度。这是我写的代码:

#include <stdio.h>

int main(){
    char str1[100], str2[100] = {'a'};

    printf("Enter a string\n");
    fgets(str1, sizeof(str1), stdin);

    int i;
    for(i = 0; str1[i] != '\0'; i++){
        str2[i] = str1[i];
    }   

    str2[i] = '\0';

    printf("Copied string = %s", str2);

    printf("Length of string = %d", i-1);
}
Run Code Online (Sandbox Code Playgroud)

我有一个相当令人惊讶的观察!即使添加了注释str2[i] = '\0',该字符串也将正确打印,即,'a'在初始化中没有多余的,据我所知,不应将其覆盖。

评论后str2[i] = '\0',我希望看到以下输出:

test
Copied string = testaaaaaaaaaaaaaaaaaaaaaaaaaaa....
Length of string = 4
Run Code Online (Sandbox Code Playgroud)

这是输出:

test
Copied string = test
Length of string = 4
Run Code Online (Sandbox Code Playgroud)

如何str2正确打印?编译器可以识别字符串的复制并静默添加空终止符吗?我正在使用gcc,但是clang也会产生类似的输出。

Mar*_*nen 8

str2[100] = {'a'};不满str2100重复a。它将str [0]设置为“ a”,其余设置为零。

早在C89:

3.5.7初始化

...

语义学

...

如果没有显式初始化具有静态存储持续时间的对象,则将隐式初始化该对象,就好像为每个具有算术类型的成员分配了0,为每个具有指针类型的成员分配了一个空指针常量。如果未自动初始化具有自动存储期限的对象,则其值不确定。/65/

...

如果列表中的初始化程序少于聚合成员,则聚合的其余部分应与具有静态存储持续时间的对象隐式初始化。