解释fprintf()在程序中的奇怪行为,在文件中打印一些不寻常的字符

Joy*_*pta -1 c io printf file

int index = 0;
FILE *fptr;
fptr = fopen("File.txt", "w");

char arr[] = {'A', '\b', 'B', '\b', 'C', '\b', '\b', '\n'};

while(arr[index] != '\0'){  
    fprintf(fptr, "%c", arr[index++]);
}
Run Code Online (Sandbox Code Playgroud)

这里从文件中获取的输出是

A|BS|B|BS|C|BS||BS|
hDC2¦v
Run Code Online (Sandbox Code Playgroud)

| BS | 是为了清晰起见,我这样写的退格字符.我无法理解为什么显示第二行输出.

Sou*_*osh 7

当你使用括号括起来的初始值列表初始化数组时

 char arr[] = {'A', '\b', 'B', '\b', 'C', '\b', '\b', '\n'};
Run Code Online (Sandbox Code Playgroud)

\0在数组的末尾没有显式附加.所以,

 while(arr[index] != '\0')
Run Code Online (Sandbox Code Playgroud)

在错误的前提下运行并访问超出范围的内存.它调用未定义的行为.

引用C11,章节§6.7.9

如果初始化未知大小的数组,则其大小由具有显式初始值设定项的最大索引元素确定.数组类型在其初始化列表的末尾完成.

另一方面,使用字符串文字初始化数组会自动将空终止符放在最后,如本章所述

字符类型数组可以由字符串文字或UTF-8字符串文字初始化,可选地用大括号括起来.字符串文字的连续字节(如果有空间或数组大小未知,则包括终止空字符)初始化数组的元素.

所以,要么

  • 添加a \0作为初始化列表的最后一个元素
  • 或者,自己计算有效的条目数,如使用sizeof(arr)/sizeof(arr[0])或类似.