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

问题描述

总体的一般问题是; 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";

此处,char 中的前 4 个 aitch 将依次为:Cat\0,\0 是空终止符。 C 中的字符串以空字符结尾。 printfstrlen 之类的函数需要一个以 NULL 结尾的字符串,一旦遇到空终止符就会停止处理该字符串。

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

,

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

char aitch[30] = "Cat";

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

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

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

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

如果你确定它们之间没有空字节,它们又会变成一个字符串。

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

,

我们这里是沟通失败了---你们评论和回答都很好,回答评论非常感谢。

问题,正如可能在其他地方也看到的那样,是关于 C 的超乎想象的可怕评论,在那里,在那里,等等,如果不梳理,就无法判断任何东西的质量通过各种各样的方式,无论在哪里找到它,并通过编写演示代码来测试一切

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

基于那个在“C”中对“字符串”的定义,那么是的,printf,尤其是 strlen 的行为不正确。

就我而言,我确实在对 C 进行自动驾驶研究和深入挖掘,并且不得不涉足许多此类相当垃圾的文档实例。因此,出于自卫,我正在写我自己的笔记,并使用绝对有效的示例代码块来支持所有内容。

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

这个例子不会是我在继续学习时遇到的最后一个评论混乱。---不,我不知道下一个混乱会是什么,我只知道会有是一个,然后是下一个,然后是下一个。 . . .