ANSI C中的字符串

时间:2012-07-23 13:41:29

标签: c

这是C语言的第三个程序。 该程序用于演示字符串概念。

从研究中我知道字符串末尾有一个空字符'\ 0'来终止字符串。

我写了那段代码:

main()
{
      char  name[8];

      strcpy(name, "Mahmoud");
      printf("The contents of name are %s\n", name);
      getchar();
}

在这段代码中,我声明了char类型的数组以保存字符串。我的名字“Mahmoud”是7个字符,我声明大小为8的名称,“Mahmoud”为7,“\ 0”为1,并且它正常工作。

但是在下面的代码中:

main()
{
      char  name[8];

      strcpy(name, "MahmoudEmam");
      printf("The contents of name are %s\n", name);
      getchar();
}

当我显示名称时输出为“MahmoudEmam”,虽然名称的大小为8。

它是怎么做的?

5 个答案:

答案 0 :(得分:5)

C不执行任何数组边界检查(可能使用C11 ......)。您正在编写超出数组末尾的内容:它是一种未定义的行为(任何事情都可能发生)。

答案 1 :(得分:4)

您看到显示的全名的事实是未定义的行为。基本上,您将超过7个字符和一个终止0(总共8个字符)复制到仅为7个字符和终止0保留的存储中。

它恰好可以工作,但很容易导致程序崩溃。

这就是为什么C被认为是一种较低级别的编程语言,或者,就像许多年前用过的短语一样,它是一种高级汇编编程语言。

程序员必须使用类似sizeof(name)的结构检查复制操作目标的长度,并确保复制的内容不会覆盖该空间。你也必须记住 字符串终止,足够的空格+ 1来说明终止'\ 0'。

不要忘记,对于32位指针或硬件的指针长度,使用带有malloc分配的字符串的sizeof将返回值4。在这种情况下,您将不得不依赖strlen来获取缓冲区长度,或者存储用于malloc字符串的大小。

最后,当将字符串指针传递给函数时,将函数写入具有缓冲区长度非常有用。您无法获得真正的缓冲区长度。 strlen只返回字符串长度,而不是指针实际指向的缓冲区大小。

答案 2 :(得分:2)

在这种情况下你很幸运。发生了什么事情,你已经在堆栈上为7个字母的字符串分配了足够的内存(+ '\0'一个),但你正在写它之外。

C不会检测到数组边界的读/写。

所以正在发生的是,你正在编写阵列的其余部分,摧毁可能存在的任何其他内容。在较大的程序中,您很可能会遇到崩溃。

这是您应该学会使用strncpy的一个很好的示例,但请记住,如果缓冲区已满,strncpy不会添加终止'\0',您应该这样做你自己。像这样的代码可以:

strncpy(name, "the text of your string, whatever it is", sizeof(name));
name[sizeof(name) - 1] = '\0';

答案 3 :(得分:1)

您正在调用未定义的行为。你不能依赖它,因为它有效。

答案 4 :(得分:1)

问题已经得到解答,但如果可以的话,我想稍微改进一下。

如果您注意到,strcpy()不将缓冲区长度作为参数。这是因为它信任您(用户)注意不要溢出目标缓冲区。

C中没有关于您可以在内存中的哪个位置放置数据的约束。如果使用不当,这同时也是一个有力的工具和危险的工具。

当你调用printf()时,它会通过你提供的缓冲区,直到它找到第一个0并打印所有内容。如果你提供一个随机缓冲区,它将打印乱码。对于您编写的程序,您提供了一个缓冲区,其中包含您在那里复制的字符串。即使你破坏了缓冲区,该程序仍然设法找到它并打印它,因为它甚至不知道内存已损坏。

缓冲区溢出是您可以找到的最难的错误之一。它们通常会影响与导致腐败本身的模块无关的程序部分,并且通常需要很长时间才能感受到它们的效果。所以你应该小心不要造成这样的错误!