在分配了第26个元素后,尽管我为第26个索引分配了一个字符,但仍打印出“ Computer”。我期望这样的东西:“计算机K”
原因是什么?
#include <stdio.h>
int main()
{
char m1[40] = "Computer";
printf("%s\n", m1); /*prints out "Computer"*/
m1[26] = 'K';
printf("%s\n", m1); /*prints out "Computer"*/
printf("%c", m1[26]); /*prints "K"*/
}
答案 0 :(得分:4)
char s[100] = "Computer";
与
基本相同char s[100] = { 'C', 'o', 'm', 'p', 'u','t','e','r', '\0'};
由于printf在字符串以0结尾时停止,因此不会打印字符26
答案 1 :(得分:3)
在C中,字符串以0结尾。
您的初始化将'r'
之后的所有数组元素都填充为0。
如果将非0字符放置在数组的任何随机字段中,则不会更改该元素之前或之后的字段中的任何内容。
这意味着您的字符串在'r'
之后仍然以0结尾。
任何函数应该如何知道在该字符串之后可能跟随其他字符串?
答案 2 :(得分:3)
在该字符串的 8th 索引处找到\0
字符,%s
仅打印直到找到\0
(字符串的结尾,用\0
)-在 26th 处出现了字符k
,但由于之前已经找到\0
而不会打印。
答案 3 :(得分:3)
那是因为在"Computer"
之后,您的数组中有一个null terminator(\0
)。如果您在此\0
之后添加字符,将不会打印该字符,因为printf()
在遇到空终止符时会停止打印。
答案 4 :(得分:3)
每当部分初始化数组时,其余元素都将填充为零。 (这是C标准C17 6.7.9§19中的规则。)
因此char m1[40] = "Computer";
最终在内存中像这样:
[0] = 'C'
[1] = 'o'
...
[7] = 'r'
[8] = '\0' // the null terminator you automatically get by using the " " syntax
[9] = 0 // everything to zero from here on
...
[39] = 0
当然,\0
和0
的含义相同,值为0。这两种情况都将被解释为空终止符。
如果继续进行操作并覆盖索引26,然后将数组打印为字符串,它将一直打印直到遇到索引8处的第一个空终止符。
但是,如果您这样做:
#include <stdio.h>
int main()
{
char m1[40] = "Computer";
printf("%s\n", m1); // prints out "Computer"
m1[8] = 'K';
printf("%s\n", m1); // prints out "ComputerK"
}
您覆盖了空终止符,而恰好在数组中的下一个零将被视为空终止符。这段代码之所以有效,是因为我们部分初始化了数组,所以我们知道后面还有更多的零。
您改写了
int main()
{
char m1[40];
strcpy(m1, "Computer");
这不是初始化,而是运行时分配。 strcpy
仅将索引0设置为8(“计算机”,在索引8处为空)。其余元素将保留为未初始化的垃圾值,并且写入m1[8] = 'K'
将破坏该字符串,因为该字符串将不再可靠地以null终止。尝试打印时会出现未定义的行为:类似垃圾输出或程序崩溃。
答案 5 :(得分:-1)
作为其他用户答案的补充-您应该通过更加主动地学习来尝试回答您的问题。编写一个简单的程序足以了解正在发生的事情。
int main()
{
char m1[40] = "Computer";
printf("%s\n", m1); /*prints out "Computer"*/
m1[26] = 'K';
for(size_t index = 0; index < 40; index++)
{
printf("m1[%zu] = 0x%hhx ('%c')\n", index, (unsigned char)m1[index], (m1[index] >=32) ? m1[index] : ' ');
}
}