C 初始化后分配给数组中的特定索引

C 初始化后分配给数组中的特定索引,c,arrays,initialization,c-strings,C,Arrays,Initialization,C Strings,在指定了第26个元素之后,当打印时,尽管我给第26个索引指定了一个字符,仍然会打印出“计算机”。我期望像这样的东西:“计算机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"

在指定了第26个元素之后,当打印时,尽管我给第26个索引指定了一个字符,仍然会打印出“计算机”。我期望像这样的东西:“计算机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"*/
}
#包括
int main()
{
字符m1[40]=“计算机”;
printf(“%s\n”,m1);/*打印出“计算机”*/
m1[26]=‘K’;
printf(“%s\n”,m1);/*打印出“计算机”*/
printf(“%c”,m1[26]);/*打印“K”*/
}

在C中,字符串以0结尾。 您的初始化使用0填充
'r'
之后的所有数组元素。 如果在数组的任意字段中放置非0字符,这不会更改该元素之前或之后字段中的任何内容

这意味着您的字符串在
'r'
之后仍然以0结尾。
任何函数如何知道该字符串之后可能会有其他字符串?

在C中,字符串以0结尾。
char s[100] = "Computer";
您的初始化使用0填充
'r'
之后的所有数组元素。 如果在数组的任意字段中放置非0字符,这不会更改该元素之前或之后字段中的任何内容

这意味着您的字符串在
'r'
之后仍然以0结尾。 任何函数如何知道该字符串之后可能会出现其他字符串

char s[100] = "Computer";
基本上与

char s[100] = { 'C', 'o', 'm', 'p', 'u','t','e','r', '\0'};
由于printf在字符串以0结尾时停止,因此不会打印字符26

基本上与

char s[100] = { 'C', 'o', 'm', 'p', 'u','t','e','r', '\0'};

由于printf在字符串以0结尾时停止,因此它不会在该字符串的第8个索引处打印字符26

,找到
\0
字符,
%s
只打印到找到
\0
(字符串的末尾,用
\0
标记)-在26处,字符
k
已存在,但不会打印,因为在此之前已找到
\0

在该字符串的第8个索引处,找到
\0
字符,
%s
仅打印,直到找到
\0
(字符串的末尾,用
\0
标记)-在26处,字符
k
在那里,但它不会被打印,因为在此之前找到了
\0

这是因为在
之后的“计算机”
数组中有一个(
\0
)。如果在此
\0
之后添加一个字符,它将不会被打印,因为
printf()
遇到空终止符时会停止打印。

这是因为在
“计算机”
之后,数组中有一个(
\0
)字符。如果在此
\0
之后添加一个字符,它将不会被打印,因为
printf()
遇到空终止符时会停止打印。

每当部分初始化数组时,其余元素都会被零填充。(这是C标准C17 6.7.9§19中的规则。)

因此
charm1[40]=“计算机”以如下方式结束在内存中:

[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"
}

这不是初始化,而是运行时分配<代码>strcpy
只会将索引0设置为8(“计算机”在索引8处有空项)。剩下的元素将不初始化为垃圾值,写入
m1[8]='K'
将破坏字符串,因为它将不再可靠地以null结尾。当您试图打印它时,会出现未定义的行为:类似于垃圾输出或程序崩溃。

每当您部分初始化一个数组时,剩余的元素都会被零填充。(这是C标准C17 6.7.9§19中的规则。)

因此
charm1[40]=“计算机”以如下方式结束在内存中:

[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"
}

这不是初始化,而是运行时分配<代码>strcpy
只会将索引0设置为8(“计算机”在索引8处有空项)。剩下的元素将不初始化为垃圾值,写入
m1[8]='K'
将破坏字符串,因为它将不再可靠地以null结尾。当你试图打印它时,你会得到未定义的行为:像垃圾输出或程序崩溃。

就像其他用户的答案一样,你应该通过更加主动地学习来回答你的问题。只需编写一个简单的程序就足以理解正在发生的事情

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] : ' ');
  }

}
intmain()
{
字符m1[40]=“计算机”;
printf(“%s\n”,m1);/*打印出“计算机”*/
m1[26]=‘K’;
对于(大小索引=0;索引<40;索引++)
{
printf(“m1[%zu]=0x%hhx(“%c”)\n”,索引,(无符号字符)m1[index],(m1[index]>=32)?m1[index]:“”;
}
}

作为对其他用户答案的补充,您应该在学习中更加积极主动地回答您的问题。只需编写一个简单的程序就足以理解正在发生的事情

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] : ' ');
  }

}
intmain()
{
字符m1[40]=“计算机”;
printf(“%s\n”,m1);/*打印出“计算机”*/
m1[26]=‘K’;
对于(大小索引=0;索引<40;索引++)
{
printf(“m1[%zu]=0x%hhx(“%c”)\n”,索引,(无符号字符)m1[index],(m1[index]>=32)?m1[index]:“”;
}
}

计算机的长度小于26。编译器不是用'\0'填充其余元素吗?是的,在初始化过程中,
'r'之后添加了一系列0字节。计算机的长度为