如何返回静态变量有所作为?

时间:2014-01-09 15:45:29

标签: c

int main(){    
  char *s ;
  char *fun( ) ;
  s = fun( ) ;
  printf ( "%s", s ) ;
}

char *fun( ){    
  char buffer[30] ;
  strcpy ( buffer, "RAM - Rarely Adequate Memory") ;
  return ( buffer ) ;
}

为什么上面的代码打印出不可预测的结果?如何使char buffer [30]静态帮助?

4 个答案:

答案 0 :(得分:5)

程序的整个运行时存在一个static变量,与普通的“自动”变量不同,只要其父范围存在,该变量才存在。

如果确实返回了指向非static变量的指针,则表示调用者获取对内存的引用,当被调用函数返回时,该引用不再保留它在函数内所执行的操作。调用者无法有效访问该内存,这样做会调用未定义的行为。

答案 1 :(得分:2)

自动变量驻留在(函数调用)堆栈上。因此,当调用下一个函数时,(在此示例中为printf),堆栈内容将被覆盖。因此出现了不可预测的错误。

然而,静态变量存储在数据段中。 (与全局变量非常相似,只要考虑存储。)

因此,在下一个函数调用期间不会覆盖静态变量。因此它工作正常。

答案 2 :(得分:0)

char buffer[30];

该行为堆栈上的缓冲区分配空间。当函数退出时,存储将消失,并将被printf中声明的自动变量覆盖。

static char buffer[30];

导致缓冲区从程序的数据段分配,因此在调用printf时不会被覆盖。但是,因为它只被分配一次,所以每次调用fun都会覆盖以前的值(对你来说不是问题,因为你正在将一个常量字符串写入其中。

答案 3 :(得分:0)

在代码中

char *fun( ){    
  char buffer[30] ;
  strcpy ( buffer, "RAM - Rarely Adequate Memory") ;
  return ( buffer ) ;
}

buffer数组仅在函数本身的生命周期内存在;函数退出后,buffer使用的内存可供其他线程或进程使用。这意味着在执行语句之间的时间

s = fun( ) ;
printf ( "%s", s ) ;

另一个线程或进程可能会覆盖buffer正在使用的内存。

如果您将buffer声明为static,例如

char *fun( ){    
  static char buffer[30] ;
  strcpy ( buffer, "RAM - Rarely Adequate Memory") ;
  return ( buffer ) ;
}

然后buffer使用的内存在程序启动时分配并保持到程序终止,这意味着没有其他内容可以覆盖它。然而,这需要付出代价; fun不再是re-entrant。由于函数当前已写入,因此它不是问题,因为它为任何调用返回相同的值。但是,如果fun意味着针对不同情况返回不同的字符串,则如果一个调用被另一个调用中断,则可能会遇到问题。

第三种选择是动态分配buffer的内存:

char *fun( ){    
  char *buffer = malloc( sizeof *buffer * 30 ) ;
  if ( buffer )
    strcpy ( buffer, "RAM - Rarely Adequate Memory") ;
  return ( buffer ) ;
}

这解决了前两个问题;函数退出后保留缓冲区的内容,并且您不限于单个静态缓冲区。但由于没有免费午餐这样的东西,现在调用函数必须确保在完成它时释放该内存:

int main(){    
  char *s ;
  char *fun( ) ;
  s = fun( ) ;
  printf ( "%s", s ) ;
  free( s );
}