C编程中对字符串的混淆

标签 c printf string-literals c-strings array-initialization

所以我正在学习使用编译器 Dev C++ 编写 C 语言程序。 问题一:

#include <stdio.h> 
#include <conio.h> //for the getch() function
#include <string.h> 

int main(void) 
{ 
    char line[3]; 
    strcpy(line, "Hello world"); 
    printf("%s", line); 
    getch(); 
} 

输出: 世界,你好

为什么当我声明我的字符串只包含 3 个字符时它显示所有的“Hello world”?

问题二:

char line[3] = "Hello world"; 
printf("%s", line); 

输出: 帮助

为什么会显示“Hel”?由于 line[0] = H、line[1] = e 和 line[2] = '\0',它不应该只显示“He”吗? %s 是通过搜索 '\0' 来工作的吗?

请帮助我了解实际情况。谢谢!

最佳答案

Please help me understand whats really happening.

未定义的行为!

当你这样做时,你有一个 buffer overrun :

char line[3]; 
strcpy(line, "Hello world"); 

Why is it that it displays all of "Hello world" when i declared my string to only hold 3 characters?

您正在复制超过分配数组的大小。这是未定义的行为,因此任何输出都是可能的,包括但不限于调用蒂尔达阿姨、格式化硬盘等:) See here了解更多。


char line[3] = "Hello world"; 
printf("%s", line); 

这是一个 buffer over-read !引用alk's answer关于为什么只有 3 个字符会被复制到 line

Why is it that it displays "Hel"? Shouldnt it display only "He"

不,它可以显示任何东西,同样是因为未定义的行为。查看我在我的机器上得到的输出:

Hel☻

这是未定义的行为,因为 printf 期望您有一个以 null 结尾的字符串,是的,但这并不意味着您可以访问超出数组大小的内容,即您有一个数组内存中的这个

                 [0] [1] [2]
-----------------------------------------------
. . . █ | █ | █ | H | e | l | █ | █ | █ | . . .
-----------------------------------------------
                <-- line --->

上面写为 █ 的任何东西都是未知值,不在你的权力之下,因此访问它们是未定义的。但是,printf 中的 %s 需要一个以 null 结尾的字符串,因此,根据您的命令,它读取的内容超出了允许的范围(允许的只有三个元素,直到 l).在我的例子中 \0 出现在 l (笑脸)之后的一个元素,而在你的例子中它就在 l 之后因此看起来正确但只有运气好的话,1000个元素以后可能会出现。


如果您真的想打印 char 数组,它不是以 null 结尾的,并且只打印到允许的限制,您可以执行其中之一而不会遇到任何未定义的行为。

printf("%.3s", line);       // length specified at compile-time

printf("%.*s", 3, line);    // length fed at run-time

See here了解更多信息。

关于C编程中对字符串的混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25094299/

相关文章:

指针调用和值调用 C

c - strtok 不返回所有标记

C++0x printf() 为 double 打印错误的值

c - 在 C 中,指针值更改后内存值会发生什么情况?

c++ - 当一个函数可以被赋予一个 char* 或文字字符串时,声明这个函数的正确方法是什么?

c - 确保线程中的所有 Printf 都实际打印

java - Printf 在 Java 中的使用

c - C中printf()中单引号和双引号的区别

c++ - 如何使用取决于模板参数的字符类型定义字符串文字?

我们可以在 C 的 main 函数中定义函数原型(prototype)吗?