无法预测以下程序的输出
Unable to predict the ouput of the following program
我对悬挂指针有一个想法。我知道下面的程序会产生悬空 pointer.But 我无法理解程序的输出
char *getString()
{
char str[] = "Stack Overflow ";
return str;
}
int main()
{
char *s=getString();
printf("%c\n",s[1]);
printf("%s",s); // Statement -1
printf("%s\n",s); // Statement -2
return 0;
}
下面程序的输出是
吨
如果只有 Statement-1 存在,那么输出是一些抓取值
如果只有 Statement-2 则输出为新行
您的代码显示 undefined behaviour,因为您正在 return 获取局部变量的地址。
一旦 getString()
函数完成执行并且 returned.
就不存在 str
至于问题,
if only Statement-1 is there then output is some grabage values if only Statement-2 is there then output is new line
没有解释。一旦您的程序表现出未定义的行为,就无法预测输出,仅此而已。 [谁知道呢,它也可能会打印你的手机 phone 号码,或者一个守护进程可能会从我的鼻子里飞出来]
对于简单的逻辑部分,在printf()
中添加一个\n
将导致输出缓冲区立即刷新到输出。 [提示:stdout
是行缓冲的。]
解法:
您可以通过以下两种方式之一完成工作
- 取一个指针,在
getString()
和return指针内部动态分配内存。 (我会推荐这个)。此外,free()
稍后在 main()
完成后。
- make
char str[]
static
使范围不限于函数的生命周期。 (不太好,但还是可以的)
你getString
中的str
是一个局部变量,分配在栈上,当函数returns时,它不存在了
我建议你这样重写getString()
char *getString()
{
char str[] = "Stack Overflow ";
char *tmp = (char*)malloc(sizeof(char)*strlen(str));
memcpy(tmp, str, strlen(str));
return tmp;
}
你还需要添加
free(s);
之前 return 0;
在我的例子中,指针 tmp
指向堆上的一块内存,它将一直存在到你的程序结束
你需要了解更多 stack and heap
除此之外,还有一种方法,使用静态变量代替
char *getString()
{
static char str[] = "Stack Overflow ";
return str;
}
PS:你得到以下陈述的正确答案printf("%c\n",s[1]);
只是巧合。当您 return 退出函数时,操作系统没有时间做一些清理工作。但是会
数组被 return 编辑为指针,但数组本身是函数 return 之后的垃圾。只需使用静态修饰符。
关于s[1]的事情没问题。关键是,它是获得悬挂指针后的 first printf。因此,此时的堆栈仍然(可能)完好无损。你应该还记得堆栈只用于函数调用和局部变量(在 DOS 中它可以被系统中断使用,但现在不是这样了)。因此,在第一个 printf 之前(当 s[1] 被计算时),s[] 是可以的,但是之后 - 它不是(printf 代码搞砸了)。我希望,现在一切都清楚了。
我对悬挂指针有一个想法。我知道下面的程序会产生悬空 pointer.But 我无法理解程序的输出
char *getString()
{
char str[] = "Stack Overflow ";
return str;
}
int main()
{
char *s=getString();
printf("%c\n",s[1]);
printf("%s",s); // Statement -1
printf("%s\n",s); // Statement -2
return 0;
}
下面程序的输出是 吨 如果只有 Statement-1 存在,那么输出是一些抓取值 如果只有 Statement-2 则输出为新行
您的代码显示 undefined behaviour,因为您正在 return 获取局部变量的地址。
一旦 getString()
函数完成执行并且 returned.
str
至于问题,
if only Statement-1 is there then output is some grabage values if only Statement-2 is there then output is new line
没有解释。一旦您的程序表现出未定义的行为,就无法预测输出,仅此而已。 [谁知道呢,它也可能会打印你的手机 phone 号码,或者一个守护进程可能会从我的鼻子里飞出来]
对于简单的逻辑部分,在printf()
中添加一个\n
将导致输出缓冲区立即刷新到输出。 [提示:stdout
是行缓冲的。]
解法:
您可以通过以下两种方式之一完成工作
- 取一个指针,在
getString()
和return指针内部动态分配内存。 (我会推荐这个)。此外,free()
稍后在main()
完成后。 - make
char str[]
static
使范围不限于函数的生命周期。 (不太好,但还是可以的)
你getString
中的str
是一个局部变量,分配在栈上,当函数returns时,它不存在了
我建议你这样重写getString()
char *getString()
{
char str[] = "Stack Overflow ";
char *tmp = (char*)malloc(sizeof(char)*strlen(str));
memcpy(tmp, str, strlen(str));
return tmp;
}
你还需要添加
free(s);
之前 return 0;
在我的例子中,指针 tmp
指向堆上的一块内存,它将一直存在到你的程序结束
你需要了解更多 stack and heap
除此之外,还有一种方法,使用静态变量代替
char *getString()
{
static char str[] = "Stack Overflow ";
return str;
}
PS:你得到以下陈述的正确答案printf("%c\n",s[1]);
只是巧合。当您 return 退出函数时,操作系统没有时间做一些清理工作。但是会
数组被 return 编辑为指针,但数组本身是函数 return 之后的垃圾。只需使用静态修饰符。
关于s[1]的事情没问题。关键是,它是获得悬挂指针后的 first printf。因此,此时的堆栈仍然(可能)完好无损。你应该还记得堆栈只用于函数调用和局部变量(在 DOS 中它可以被系统中断使用,但现在不是这样了)。因此,在第一个 printf 之前(当 s[1] 被计算时),s[] 是可以的,但是之后 - 它不是(printf 代码搞砸了)。我希望,现在一切都清楚了。