C中的'\ 0'和printf()


21

在C的入门课程中,我了解到在存储字符串的同时,在字符串\0末尾存储了空字符。但是,如果我想打印一个字符串,该怎么办,printf("hello")尽管我发现它并没有以\0以下语句结尾

printf("%d", printf("hello"));

Output: 5

但这似乎是不一致的,据我所知,像字符串这样的变量存储在主存储器中,我想在打印内容时也可能将其存储在主存储器中,那为什么会有区别呢?


1
除了您的代码至少遗漏之外,);您打算用该代码显示什么?您如何证明它不以\0?结尾?
glglgl

它存储的内存与它有什么关系?
Tsakiroglou Fotis

在C语言中,所有文字字符串实际上都是字符数组,其中包括空终止符。
一些程序员老兄

@glglgl我认为printf()返回应该在屏幕上打印的字符数。
Ajay Mishra

4
@AjayMishra是的,确实应该打印5个字符。屏幕上不打印终止的0字节。
glglgl

Answers:


13

空字节标记字符串的结尾。当使用来打印字符串时,它不会计入字符串的长度,也不会打印出来printf。基本上,空字节告诉执行字符串操作的函数何时停止。

您将看到差异的地方是您是否创建了一个char用字符串初始化的数组。使用sizeof运算符将反映包括空字节在内的数组的大小。例如:

char str[] = "hello";
printf("len=%zu\n", strlen(str));     // prints 5
printf("size=%zu\n", sizeof(str));    // prints 6

我认为故事会有所不同printf()。TBH我不知道如何printf()运作。
Ajay Mishra

8

printf返回打印的字符数。'\0'未打印-只是表示该字符串中不再有char。它也不计入字符串长度

int main()
{
    char string[] = "hello";

    printf("szieof(string) = %zu, strlen(string) = %zu\n", sizeof(string), strlen(string));
}

https://godbolt.org/z/wYn33e

sizeof(string) = 6, strlen(string) = 5

6

您的假设是错误的。您的字符串确实以结尾\0

它包含5个字符hello和0字符。

“内部” print()调用输出的是打印的字符数,即5。


6

在C语言中,所有文字字符串实际上都是字符数组,其中包括空终止符。

但是,空终止符计入字符串的长度(无论是否为文字),也不会打印出来。找到空终止符后,打印将停止


反正有没有在不将字符串存储在数组中的情况下进行验证?
Ajay Mishra

1
@AjayMishra那么字符串已经一个数组(如前所述)......但是,如果没有一个空终止然后printf会出去串的界限,并打印“随机”或“垃圾”字符,并返回与字符串长度不同的数字。如果您已经知道字符串的长度,则还可以检查该索引处的字符是否为,该字符是否可以'\0'工作,但是如果数组的大小不包含终止符(如中的char arr[5] = "hello";,则不会添加字符),该行为在技术上是未定义的行为数组的终止符)。
一些程序员老兄

@AjayMishra是的,例如,您可以char * p = "Hello"; int i = 0; while (p[i] != '\0') { printf("%d: %c", i, p[i]); i++; }查看其运行方式:它显示带有索引的行以及该行的内容。在索引4之后,它找到0字符并中断while循环。在那里,您看到一个0字符。
glglgl

6

所有答案都非常好,但我想添加另一个示例来完成所有这些步骤

#include <stdio.h>

int main()
{
    char a_char_array[12] = "Hello world";

    printf("%s", a_char_array);
    printf("\n");

    a_char_array[4] = 0; //0 is ASCII for null terminator

    printf("%s", a_char_array);
    printf("\n");

    return 0;
}

对于那些不想在在线gdb上尝试的用户,输出为:

你好,世界

地狱

https://linux.die.net/man/3/printf

这有助于了解逃逸终止符的作用吗?它不是char数组或字符串的边界。这是对要解析-STOP的人说的字符,(打印)解析到这里为止。

PS:如果您解析并将其打印为char数组

for(i=0; i<12; i++)
{
    printf("%c", a_char_array[i]);
}
printf("\n");

你得到:

地狱世界

其中,双倍l之后的空白是空终止符,但是,解析一个char数组时,它将只是每个字节的char值。如果进行另一次分析并打印每个字节的int值(“%d%,char_array [i]),则会看到(获得ASCII码int表示形式)空白值为0。


4

C函数printf()返回打印的字符数,\0null它用来表示在C语言中字符串的结束,并没有内置在终止string类型的c++,但是你的数组大小需要是至少大于数目char你想储藏。

这是参考:cpp ref printf()


3

但是,如果我想打印一个字符串,请说一下printf(“ hello”),尽管我发现以下语句不会以\ 0结尾

printf("%d", printf("hello"));

Output: 5

你错了。该语句不能确认字符串文字"hello"不以结尾的零字符结尾'\0'。该语句确认函数将printf输出字符串的元素,直到遇到终止的零字符为止。

当您使用上述语句中的字符串文字时,编译器会创建一个具有静态存储持续时间的字符数组,其中包含字符串文字的元素。

所以实际上这个表达

printf("hello")

由编译器处理,如下所示

static char string_literal_hello[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
printf( string_literal_hello );

您可以通过以下方式想象函数printf的作用

int printf( const char *string_literal )
{
    int result = 0;

    for ( ; *string_literal != '\0'; ++string_literal )
    {    
        putchar( *string_literal );
        ++result;
    }

    return result;
}

要获取存储在字符串文字“ hello”中的字符数,您可以运行以下程序

#include <stdio.h>

int main(void) 
{
    char literal[] = "hello";

    printf( "The size of the literal \"%s\" is %zu\n", literal, sizeof( literal ) );

    return 0;
}

程序输出为

The size of the literal "hello" is 6


0

字符串是字符的向量。包含构成字符串的字符序列,后跟特殊的结尾字符串:“ \ 0”

例如:char str [10] = {'H','e','l','l','o','\ 0'};

示例:以下字符向量不是一个字符串,因为它不以'\ 0'结尾

char str [2] = {'h','e'};


我猜C中没有向量。
Ajay Mishra
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.