C 字符串初始化中的明显异常:printf 和 strlen 似乎都出错了?

Apparent oddity in C string initialization: printf and strlen both seem to be in error?

总体问题是; C 中关于字符串初始化的一些奇怪之处似乎没有人评论我可以找到对/是否有一些特定的 Googlemancy 术语来研究我偶然发现的一个奇怪之处/是我还是有某种printf 和 strlen 如何处理 C 中的特定字符串的“错误”或“功能”?

我发现虽然 printf 应该打印字符串,但它只打印了字符串的一部分。我发现虽然 strlen 应该报告字符串的长度,但它只报告了它的一部分。

我是否发现了某种错误,或者这是 C 的一个相当非常晦涩的“特性”,在这种情况下,此类的详细信息和讨论术语一个“功能”?

考虑这段代码,以及随后的输出:

代码:

/* Header files for program support */
#include <stdio.h>
#include <string.h>

    /* The primary program section */
int main(void)
{

    /* Variable declaration and initialization*/
    char aitch[30] = "Cat";

    /* What gets done here */
    printf("The string aitch is: %s.\n", aitch);
    printf("strlen says aitch is %lu characters long.\n", strlen(aitch));
    printf("aitch[10] is what is between >> and <<: >>%c<<.\n\n", aitch[10]);

    printf("Now dish out a bunch of chopped liver.\n\n");


    /* More variable declaration and initialization*/
    aitch[11] = ' '; aitch[12] = 'C'; aitch[13] = 'h'; aitch[14] = 'o'; 
    aitch[15] = 'p'; aitch[16] = 'p'; aitch[17] = 'e';  aitch[18] = 'd'; 
    aitch[19] = ' '; aitch[20] = 'l'; aitch[21] = 'i'; aitch[22] = 'v'; 
    aitch[23] = 'e'; aitch[24] = 'r';

    /* Looking over the new stuff */
    printf("aitch listed by character at this point is:\n\n");

    printf("%c", aitch[0]); printf("%c", aitch[1]); 
    printf("%c", aitch[2]); printf("%c", aitch[3]); 
    printf("%c", aitch[4]); printf("%c", aitch[5]); 
    printf("%c", aitch[6]); printf("%c", aitch[7]); 
    printf("%c", aitch[8]); printf("%c", aitch[9]); 
    printf("%c", aitch[10]); printf("%c", aitch[11]); 
    printf("%c", aitch[12]); printf("%c", aitch[13]); 
    printf("%c", aitch[14]); printf("%c", aitch[15]); 
    printf("%c", aitch[16]); printf("%c", aitch[17]); 
    printf("%c", aitch[18]); printf("%c", aitch[19]); 
    printf("%c", aitch[20]); printf("%c", aitch[21]); 
    printf("%c", aitch[22]); printf("%c", aitch[23]); 
    printf("%c", aitch[24]); printf("\n\n");

    /* Hang on, what was that last bit? */
    printf("printf still says all of aitch is %s.\n", aitch);
    printf("strlen still says all of aitch is %lu characters long.\n", 
        strlen(aitch));
    printf("aitch[10] is still what is between >> and <<:  >>%c<<.\n\n", aitch[10]);

    printf("Now put something in the empty area.\n\n");

    /* More variable declaration and initialization*/
    aitch[3] = '_'; aitch[4] = '_'; aitch[5] = '_'; aitch[6] = '_';
    aitch[7] = '_'; aitch[8] = '_'; aitch[9] = '_';  aitch[10] = '_'; 

    /* Ok, _Now_ what??? */
    printf("printf now says all of aitch is:\n\n%s.\n\n", aitch);
    printf("strlen says all of aitch _now_ is %lu characters long.\n", 
        strlen(aitch));
    printf("aitch[10] is now what is between >> and <<:  >>%c<<.\n\n", aitch[10]);

}

输出:

% ./a.out
The string aitch is: Cat.
strlen says aitch is 3 characters long.
aitch[10] is what is between >> and <<: >><<.

Now dish out a bunch of chopped liver.

aitch listed by character at this point is:

Cat Chopped liver

printf still says all of aitch is Cat.
strlen still says all of aitch is 3 characters long.
aitch[10] is still what is between >> and <<:  >><<.

Now put something in the empty area.

printf now says all of aitch is:

Cat________ Chopped liver.

strlen says all of aitch _now_ is 25 characters long.
aitch[10] is now what is between >> and <<:  >>_<<.
char aitch[30] = "Cat";

在这里,aitch中的前4个char依次为:Cat[=16 =],其中 [=16=] 是空终止符。 C 中的字符串以 null 结尾。 printfstrlen 等函数期​​望以 NULL 结尾的字符串,并且一旦遇到空终止符就会停止处理该字符串。

当您直接写入 aitch[3] 时,您会覆盖空终止符。

在C语言中,一个字符串是:一系列字符,以空字符(0字节)结尾。

char aitch[30] = "Cat";

这声明了一个包含 30 个字符的数组。第一个是'C',第二个是'a',第三个是't',第四个是null(结束字符串),其余都是null(默认)。 (注意:char aitch[30]; 本身不会使它们全部为空)

所以你有 space 30 个字符。如果您从第一个字符开始使用 space,则该 space 中存储了一个有效的字符串:'C'、'a'、't'、0。那是一个长度为 3 个字符的字符串。如果您调用 strlen 它将 return 3 因为那是字符串的长度。如果你打印它,它会打印 3 个字符,因为这就是字符串的长度。

请注意,30 个字符的 space 与 30 个字符的字符串不同。 space就是space,字符串就是你实际存储在那里的数据。您有 26 个不属于字符串的字符,您可以根据需要使用它们。

事实上,你有足够的space来存储两个不同的字符串!这正是您在代码中所做的。

如果你确定它们之间没有空字节,它们就会再次成为一个字符串。

请注意,字符串的任何“结尾部分”也是有效的字符串。如果您从数组中的位置 0 开始,您将得到字符串“Cat”。但是如果你从位置 1 开始,你得到“at”,如果你从位置 2 开始,你得到“t”,如果你从位置 3 开始,你得到“”。一切都很好用。

我们这里遇到的是沟通失败---大家的评论和回答都很好,非常感谢回答评论。

问题,可能在其他地方也已经看到,是对 C 的超现实可怕的评论,在那里,在那之外,等等,无法告诉任何东西的质量,无论在哪里找到它,都不需要经过各种各样的梳理,并通过编写演示代码来测试一切

在这种情况下,一个非常特殊的例子是相当多的书评、在线评论等等,它们声明 char aitch[30] 本质上是一个 30 个字符长的字符串的创建,然后一个初始化这里和那里 。 . . 据此,无论是一组字符还是分开的两个或多个字符都无关紧要,都是一个字符串。

基于“C”中“string”的定义,是的,printf 尤其是 strlen 的行为不正确。

就我而言,我确实正在对 C 进行自我驱动研究和深入挖掘,并且不得不费力地浏览许多此类非常垃圾文档的实例。因此,出于自我防卫,我边走边写自己的笔记,使用绝对有效的示例代码块来支持所有内容。

---关于循环可以放入示例代码的评论,基本上是的,但迂腐地,还没有---我正在做的笔记目前正在首先从函数开始后梳理变量, 循环将持续一两章。

在我继续学习的过程中,这个实例不会是我要 运行 进入的最后一个评论混乱。---不,我不知道下一个混乱会是什么,我只知道会有一个,然后是下一个,然后是下一个。 . . .