C语言中的指针和函数歧义

C语言中的指针和函数歧义,c,function,pointers,C,Function,Pointers,请查看以下代码: char* test ( ) { char word[20]; printf ("Type a word: "); scanf ("%s", word); return word; } void main() { printf("%s",test()); } 当函数返回时,变量word被销毁,并打印一些垃圾值。但当我替换 char word[20]; 通过char*字 它打印正确的值。根据我的说法,指针变量应该像字符数组一样被销毁,

请查看以下代码:

char* test ( )
{
    char word[20];
    printf ("Type a word: ");
    scanf ("%s", word);
    return word;
}

void main()
{
    printf("%s",test());
}
当函数返回时,变量
word
被销毁,并打印一些垃圾值。但当我替换

char word[20];
通过
char*字


它打印正确的值。根据我的说法,指针变量应该像字符数组一样被销毁,并且输出应该是一些垃圾值。谁能解释一下这种模糊性吗?

未定义的行为就是这样-未定义。有时它似乎会起作用,但那只是巧合。在这种情况下,可能未初始化的指针恰好指向有效的可写内存,而该内存不用于任何其他用途,因此它成功地写入和读取了该值。这显然不是你应该依赖的东西。

无论哪种方式,你都有未定义的行为,但纯粹从“这里发生了什么”的角度来看,两者之间仍然存在一些差异

使用数组时,它所保存的数据将在堆栈上分配。当函数返回时,该内存将不再是堆栈的一部分,并且几乎肯定会在调用
printf
的过程中被覆盖

当您使用指针时,您的数据将被写入指针所指向的任意随机位置。尽管在那里写是未定义的行为,但简单的统计数据表明,如果您(例如)有一个约40亿个位置的32位地址空间,那么在新的几条指令中命中一个将被覆盖的地址空间的可能性相当低


显然,您不应该执行任何一项操作,但得到的结果也并不特别令人惊讶。

因为char数组是在函数中定义和声明的,它是一个局部变量,在函数返回后不再存在。如果您使用char指针并为其分配内存,那么它将保持不变,您所需要的只是指针(也称为数字)


请注意我是如何使用%19s而不是%s的。如果用户输入20个或更多字符,则当前函数很容易导致缓冲区溢出。

首先在程序执行期间,它将在进程内存的堆栈段中为函数
main
创建激活记录。在
main
激活记录中,它将为该函数的局部变量(
main
)分配内存,并为内部用途分配更多内存。在您的程序中,
main
没有任何局部变量,因此它不会为
main
激活记录中的局部变量分配任何内存

然后,在执行调用函数
test
的语句时,它将为调用函数(
test
)创建一个或多个激活记录,并为局部变量
word
分配
20
字节

一旦控件退出函数
测试
,为该函数创建的激活记录将弹出该堆栈。然后它将继续执行被调用函数
main
的剩余语句(
printf
)。这里printf试图打印
test
函数的局部变量中的字符,该变量已经从堆栈中弹出。所以这种行为是未定义的,有时它可能会打印正确的字符串,或者它会打印一些垃圾字符串

所以在这种情况下,只有动态内存进入画面。借助动态内存,我们可以控制变量的生存期(或范围)。因此,使用动态内存,如下所示

char *word = NULL:
word = (char *) malloc(sizeof(char) * 20);

注意:注意malloc返回值的NULL检查,也不要忘记在main函数中
printf
之后释放分配的内存。

在这里使用
char*
将导致未定义的行为,因为您没有分配任何存储。但它给出了正确的答案!!!“未定义的行为”并不意味着“将崩溃”或“将给出意外的结果”……但当使用指针而不分配memory@AndroidDecoded:一旦您将某个内容写入内存(假设您成功写入),它将一直保留在内存中,直到电源断开或被某个内容覆盖。纯粹是因为运气不好,您刚好找到了一个位置,但没有被接下来的几个指令覆盖。
char *word = NULL:
word = (char *) malloc(sizeof(char) * 20);