初始化后分配给数组中的特定索引
Assignment after initialization to specific index in an array
分配第 26 个元素后,打印时,尽管我为第 26 个索引分配了一个字符,但仍然打印出 "Computer"。我期待这样的事情:"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"*/
}
在 C 中,字符串以 0 结尾。
您的初始化用 0 填充 'r'
之后的所有数组元素。
如果您在数组的任何随机字段中放置一个非 0 字符,这不会更改该元素之前或之后的字段中的任何内容。
这意味着您的字符串在 'r'
之后仍然以 0 结尾。
任何函数应该如何知道在该字符串之后可能会跟随其他字符串?
char s[100] = "Computer";
与
基本相同
char s[100] = { 'C', 'o', 'm', 'p', 'u','t','e','r', '[=11=]'};
由于 printf 在字符串以 0 结尾时停止,因此不会打印字符 26
在该字符串的 8th 索引处找到 [=10=]
字符并且 %s
仅打印直到找到 [=10=]
(结束字符串,由 [=10=]
) 标记 - 在 26th 处,字符 k
在那里,但不会打印,因为在此之前找到了 [=10=]
。
那是因为在 "Computer"
之后您的数组中有一个 null terminator ([=11=]
)。如果在这个 [=11=]
之后添加一个字符,它不会被打印,因为 printf()
在遇到空终止符时停止打印。
每当你部分初始化一个数组时,剩余的元素都用零填充。 (这是 C 标准中的一条规则,C17 6.7.9 §19。)
因此 char m1[40] = "Computer";
最终在内存中是这样的:
[0] = 'C'
[1] = 'o'
...
[7] = 'r'
[8] = '[=10=]' // the null terminator you automatically get by using the " " syntax
[9] = 0 // everything to zero from here on
...
[39] = 0
现在当然 [=14=]
和 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("Computer",索引 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] : ' ');
}
}
分配第 26 个元素后,打印时,尽管我为第 26 个索引分配了一个字符,但仍然打印出 "Computer"。我期待这样的事情:"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"*/
}
在 C 中,字符串以 0 结尾。
您的初始化用 0 填充 'r'
之后的所有数组元素。
如果您在数组的任何随机字段中放置一个非 0 字符,这不会更改该元素之前或之后的字段中的任何内容。
这意味着您的字符串在 'r'
之后仍然以 0 结尾。
任何函数应该如何知道在该字符串之后可能会跟随其他字符串?
char s[100] = "Computer";
与
基本相同char s[100] = { 'C', 'o', 'm', 'p', 'u','t','e','r', '[=11=]'};
由于 printf 在字符串以 0 结尾时停止,因此不会打印字符 26
在该字符串的 8th 索引处找到 [=10=]
字符并且 %s
仅打印直到找到 [=10=]
(结束字符串,由 [=10=]
) 标记 - 在 26th 处,字符 k
在那里,但不会打印,因为在此之前找到了 [=10=]
。
那是因为在 "Computer"
之后您的数组中有一个 null terminator ([=11=]
)。如果在这个 [=11=]
之后添加一个字符,它不会被打印,因为 printf()
在遇到空终止符时停止打印。
每当你部分初始化一个数组时,剩余的元素都用零填充。 (这是 C 标准中的一条规则,C17 6.7.9 §19。)
因此 char m1[40] = "Computer";
最终在内存中是这样的:
[0] = 'C'
[1] = 'o'
...
[7] = 'r'
[8] = '[=10=]' // the null terminator you automatically get by using the " " syntax
[9] = 0 // everything to zero from here on
...
[39] = 0
现在当然 [=14=]
和 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("Computer",索引 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] : ' ');
}
}