2

我有以下代码和输出:-

#include<stdio.h>
int main()
{
char pal_tmp[4];
printf("Size of String Variable %d\n",sizeof(pal_tmp));
strcpy(pal_tmp,"123456789");
printf("Printing Extended Ascii: %s\n",pal_tmp);
printf("Size of String Variable %d\n",sizeof(pal_tmp));
}

输出:-

Size of String Variable 4
Printing Extended Ascii: 123456789
Size of String Variable 4

我的问题是为什么字符串变量(字符数组)接受的字符比它的容量多?它不应该只是打印1234而不是123456789

难道我做错了什么?

4

6 回答 6

9

嗯,是。你做错了什么。您在字符串中放入的字符比您应该的要多。根据 C 规范,这是错误的,被称为“未定义的行为”。

但是,相同的 C 规范并不要求编译器(或运行时)实际将其标记为错误。“未定义的行为”意味着任何事情都可能发生,包括出错、随机数据损坏或程序实际运行。

在这种特殊情况下,您的调用strcpy只是在保留内存之外写入,并将覆盖在数组之后存储的任何内容。那里可能没有什么重要的东西,这就是为什么似乎没有什么不好的事情发生。

作为一个例子,如果你在数组之后确实有一些相关的东西会发生什么,让我们添加一个变量来看看它会发生什么:

#include <stdio.h>

int main( void )
{
    char foo[4];
    int bar = 0;

    strcpy( foo, "a long string here" );
    printf( "%d\n", bar );

    return 0;
}

运行时,我会1701322855在我的机器上得到结果(你的结果可能会有所不同)。

调用strcpy破坏了bar变量的内容,导致您看到的随机输出。

于 2013-05-23T05:58:18.210 回答
2

是的,您正在覆盖不属于该缓冲区(pal_tmp)的内存。在某些情况下,这可能会起作用,在其他情况下,您可能会遇到段错误并且您的程序会崩溃。在您展示的情况下,看起来您碰巧没有覆盖任何“有用”的东西。如果您尝试编写更多内容,则更有可能覆盖有用的内容并使程序崩溃。

于 2013-05-23T05:52:50.687 回答
1

就字符串处理函数而言, C 数组char没有预定义的大小。这些函数很乐意将数组的末尾写入其他变量(),或malloc的簿记数据(更糟),或调用堆栈的簿记数据(更糟)。C 标准使这种未定义的行为,并且有充分的理由。

如果某个特定函数的版本接受一个size参数来限制它写入的数据量,请使用它。它可以保护您免受这些东西的侵害。

于 2013-05-23T05:56:41.393 回答
0

C 不跟踪字符串(或数组,或分配的内存等)的大小,所以这是你的工作。如果您创建一个字符串,您必须始终小心确保它永远不会超过您分配给它的内存量。

于 2013-05-23T05:55:36.490 回答
0

在 C 语言中,字符串被定义为字符数组或指向包含 ASCII 字符的内存部分的指针。C 中的字符串是零个或多个字符的序列,后跟一个 NULL '\0' 字符。保留 NULL 终止字符很重要,因为它是 C 定义和管理可变长度字符串的方式。所有 C 标准库函数都需要此功能才能成功运行。

如需完整参考,请参阅此

于 2013-05-23T05:56:53.740 回答
0

函数 strcpy 不知道字符数组的长度——这个函数被认为是不安全的。

您可以使用 strncpy,您可以在其中告诉缓冲区的大小,如果提供了更长的参数,则仅使用缓冲区的内存,而不会更改任何其他内容。

于 2013-05-23T05:58:10.070 回答