0

我的代码如下:

char* int2str(int val);

void main(){
 char *s = int2str(1001);
 printf("----s=%s\n",s);
}

char* int2str(int val){
  char turnStr[10];
  sprintf(turnStr, "%d", val);
  //printf("turnStr=%s\n",turnStr);
  return turnStr;
}

上面的代码打印出空字符串,但是当我取消注释该行时:printf("turnStr=%s\n",turnStr) 它能够打印出正确的字符串。我知道函数结束时堆栈空间无法返回,但我对添加时感到困惑printf("turnStr=%s\n",turnStr),它可以打印出字符串。

4

5 回答 5

1

char数组存储在int2str函数的堆栈帧中。这意味着当函数仍在运行时,堆栈上的内存是稳定且可用的。这就是您可以打印出字符串的原因。然而,一旦你从函数中返回,就不能保证内存会被维护,它可以像你亲眼所见的那样被清除或重用。

于 2020-06-15T23:48:44.783 回答
1

您正在返回对局部变量的引用char turnStr[10]。当函数退出时,该引用使用的内存被清理。所以main()你留下了一个悬空指针:char *s指向不再有效的内存。

于 2020-06-15T23:46:21.857 回答
1

精彩的!

基本问题是您返回了堆栈上某些东西的地址,并且它被其他东西改变了。我尝试了最近的 gcc,它甚至没有返回堆栈指针,所以我尝试了 gcc 4.4.5 并重现了你的行为。

我尝试将 main 更改为:

void main(){
 char *s = int2str(1001);
 printf("----s=%s\n",s);
 s = int2str(1002);
 printf("----s=%s\n",s);
}

第二个 printf() 输出 1002。

我认为正在发生的事情是 printf 有一些局部变量被放置在与您的数组相同的位置,并且如果您之前调用过 printf() 则不会使用这些变量。

请注意,它没有打印为空,而是打印为垃圾。该垃圾可能以 NUL 开头,也可能不以 NUL 开头。

无论如何,其他人都是对的,您不应该这样做。有许多解决方案,包括:

  1. 动态内存分配(这意味着您需要释放它)
  2. 传入缓冲区(添加参数......你应该传入长度)
  3. 使用静态缓冲区(线程或多次使用有问题)
  4. 按包含文本的值返回结构(可以复制超过应有的内容,这可能会导致性能问题,并且您必须将结构保存在调用者中)
  5. 完全消除此功能(这可能不是一个好的解决方案,具体取决于您在做什么)
于 2020-06-16T00:35:24.123 回答
0

返回对本地对象的引用(指针)是一种未定义的行为。许多现代编译器发出警告并用 NULL 分配这个指针 - 例如 gcc。这段代码的另一个问题是另一个 UB。您的 char 数组不够长,无法容纳字符串

如何整理(一个例子):

char* int2str(int val);

void main(){
 char *s = int2str(1001);
 printf("----s=%s\n",s);
}

char* int2str(int val){
  static char turnStr[20];
  sprintf(turnStr, "%d", val);
  //printf("turnStr=%s\n",turnStr);
  return turnStr;
}

https://godbolt.org/z/F3cx3E

于 2020-06-15T23:55:08.207 回答
0

对于根据 C 标准的初学者,main没有参数的函数应声明为

int main( void )

那就是它的返回类型应该是int

您的程序具有未定义的行为,因为从函数返回的指针指向int2str具有自动存储持续时间的本地数组,该数组在退出函数后将不再存在。所以指针会有一个无效的值。本地数组占用的内存可以被任何其他函数的调用覆盖(例如通过printfmain 调用)。

所以你必须为目标字符串动态分配内存。在函数中使用具有静态存储持续时间的本地数组不是一个好主意,因为多次调用该函数会导致先前的结果字符串被覆盖。

请注意,例如INT_MIN(函数的用户可以传递任何有效的整数值)的值可以等于-2147483648需要一个字符数组12来存储表示此类数字的字符串。

要计算所需的字符串大小,您可以使用snprintf第二个参数等于的 C 函数调用0

这是一个演示程序。

#include <stdio.h>
#include <stdlib.h>

char * int2str( int x )
{
    int n = snprintf( NULL, 0, "%d", x );

    char *s = malloc( n + 1 );

    if ( s )
    {
        snprintf( s, n + 1, "%d", x );
    }

    return s;
}

int main(void) 
{
    char *s = int2str( 1001 );

    if ( s ) puts( s );

    free( s );

    return 0;
}

它的输出是

1001
于 2020-06-16T00:05:49.837 回答