我有以下代码:
#include <stdio.h>
int main()
{
char * string = GetString();
printf("%c", *(1+string));
int j;
for (j = 0; string[j] != '\0'; j++)
printf("%c", *(j+string));
int i;
scanf("%d", &i);
return 0;
}
和函数GetString
char * GetString()
{
char string[100];
char x; // to get the chars 1 by 1
int counter = 0;
scanf("%c", &x); // i dont like do while loops
while (x != '\n')
{
string[counter] = x;
scanf("%c", &x);
counter++;
}
string[counter] = '\0';
char * stringg = string;
return stringg;
}
由于某种原因,如果我在函数内打印字符串,我得到正常输入。但如果我在主打印它我真的很奇怪的输出。问题是什么 ?
答案 0 :(得分:4)
当您返回stringg
(string
中指向本地变量GetString
的指针时,您将返回对即将回收的内存的引用。这是因为string
“生活”在GetString
的{{3}}中,并且当函数返回时堆栈框架不再存在。您有三种选择:
string
移至main
,并将指针传递给GetString
。string
内的malloc
动态分配GetString
。使用malloc
分配的内存将一直存在,直到使用free
手动释放。string
声明为static
,这意味着将在程序的stack frame中留出记忆。但是,这意味着后续调用GetString
会破坏其内容,因此如果您想将之前调用的结果保存到
GetString
您必须使用strdup
或类似内容手动复制它。在GetString
返回之前,堆栈看起来像这样:
(high address)
+---------------------+
| (main's frame) |
| ... |
+---------------------+
| (GetString's frame) |
| char string[100] |
+---------------------+ <- stack pointer
(low address)
正如您所看到的,global data segment指向GetString
框架的末尾,标志着堆栈的顶部(请注意,在大多数现代平台上,堆栈实际上向下增长)。但是当GetString
返回时,堆栈指针向上移动到main
的帧的末尾:
(high address)
+---------------------+
| (main's frame) |
| ... |
+---------------------+ <- stack pointer
| Formerly the frame |
| of GetString, now |
| (probably) garbage. |
+---------------------+
(low address)
访问不属于堆栈的东西(即,在这种情况下,在堆栈指针下方)会导致未定义的行为。(好吧,不完全 - 请参阅下面的Barak Manos的评论)你的情况,你得到垃圾。
答案 1 :(得分:2)
返回指向自动局部变量的指针会调用未定义的行为。您需要使用动态分配或使用static
说明符。
char *string = malloc(100);
或
static char string[100];
答案 2 :(得分:0)
您可以将数组传递给GetString
函数
void GetString(char string[], size_t length /* prevent overflow */)
{
char x; // to get the chars 1 by 1
int counter = 0;
if (length == 0)
{
string[0] = '\0';
return;
}
scanf("%c", &x); // i dont like do while loops
while ((x != '\n') && (counter < length - 1))
{
string[counter] = x;
scanf("%c", &x);
counter++;
}
string[counter] = '\0';
}
并在main
int main()
{
char string[100];
GetString(string, sizeof(string));
if (*string != '0')
printf("%c", *(1+string));
int j;
for (j = 0; string[j] != '\0'; j++)
printf("%c", *(j+string));
int i;
scanf("%d", &i);
return 0;
}
答案 3 :(得分:0)
[评论太久了]
要跟进iharob proposal to pass in the buffer,请参阅:
int GetString(char * str, size_t len)
{
int result = 0;
if ((NULL == str) || (0 == len))
{
result = -1;
errno = EINVAL;
}
else
{
while (1 < len)
{
result = scanf("%c", str);
if (EOF == result)
{
int errno_save = errno:
if (ferror(stdin))
{
result = -1;
errno = errno_save;
}
else
{
result = 0;
}
}
if ((0 != result) || ('\n' == *str))
{
break;
}
++str;
--len;
}
*str = '\0';
}
return result;
}
这样称呼:
int main()
{
char string[100];
int result = GetString(string, sizeof(string));
if (-1 == result)
{
perror("GetString()" failed");
exit(1);
}
...