【问题标题】:Assigning function argument to a local static variable in C,and retaining the first value in recursion将函数参数分配给C中的局部静态变量,并在递归中保留第一个值
【发布时间】:2025-12-13 11:35:01
【问题描述】:

我在尝试定义本地静态变量时遇到此错误。

初始化元素不是常量。

我想在这个递归中保留 var 的第一个值。如何通过这个? 希望您也澄清将参数分配给要防止的局部静态变量的副作用。

int function(int var)
{
static int index=var;
//some code ...
    return var==0?1:function(var-1);
}

【问题讨论】:

  • 请提供更多信息,当您收到错误消息时?什么是错误信息?你将什么 var 传递给函数?
  • 你不能。就这么简单。
  • 为什么,以及如何解决这个问题 :)

标签: c recursion static constants


【解决方案1】:

static 变量在函数启动之前就已初始化。它就像一个全局变量,只有函数范围。编译器不能使用它还不知道的值。

您可以使用辅助布尔值解决此问题:

int function(int var)
{
  static int index_is_set=0;
  static int index;
  if (!index_is_set)
  {
    index = var;
    index_is_set = 1;
  }

//some code ...
    return var==0?1:function(var-1);
}

所以当你第一次进入函数时,它会设置值,将布尔标志设置为1,这样它就不会被进一步的调用覆盖。

请注意,这作为构造并不是很有用,因为如果您要在程序中第二次递归调用您的函数(我的意思是在第一次获得结果之后),则无法重置变量(除非您将 index_is_set 设为全局,以便您可以从外部重置它)。

请注意,通过使用起始值作为额外参数,可以完全摆脱所有 static 的东西。

int function(int var, int start_value)
{
    // ...
    return var==0 ? 1 : function(var-1,start_value);
}

第一个电话是这样的:

function(20,20);

或包装在隐藏此实现的函数中:

int function_wrapper(int var)
{
    return function(var,var);
}

起始值随所有调用一起传递。消耗更多的自动变量空间,但更干净,没有记忆效应,更容易调试。

【讨论】:

  • 是的,当没有适合直接使用的可区分值来表示“尚未初始化”时,通常的做法是采用这些方法。但是,在这种情况下,似乎可以通过将 index 初始化为 -1 来省略额外的变量。 IE。一个不可能是有效索引的值。
  • @JohnBollinger 是的,在一般情况下这是不可能的,但有一些约定是可以的。不想走那条路,因为我不知道 OP 想用它做什么。
【解决方案2】:

案例:

static int index=var;

是带有初始化器的声明(参见 ISO/IEC 9899:2011 §6.7 声明)。该语句声明了一个static 变量,该变量初始化为一个值,该值必须是在编译时定义的常量。简单来说,因为值是在执行开始之前初始化的,所以必须在函数使用之前定义初始化器。

如果您想保留递归的第一个值,那么您使用的方式并不是一个好的选择,原因有很多:

  • 正如所见,该值不能使用非常数值进行赋值
  • 如果有效,下次您输入该函数时,它将被重新分配,清除第一个值
  • 局部静态变量具有无限寿命,但作用域仅限于局部函数。然后你不能从外部范围访问或初始化它。

一种解决方案可以是向函数传递第一个值的 2 个变量,并在函数的第一次调用时传递相同的值:

int function(int first_var, int var)
{
    //some code ...
    return var==0?1:function(first_var, var-1);
}
...
function(5, 5);    //First call

为了完整起见,它可以通过在没有初始化(或使用通用初始化)的静态变量的定义中破坏您的语句,然后是一个赋值ISO/IEC 9899:2011 §6.5.16 赋值运算符):

int function(int var)
{
static int index;    //Declaration
index=var;           //Assignement
//some code ...
    return var==0?1:function(var-1);
}

但是因为每次函数重新进入都会重新赋值,所以只是大废话……

【讨论】: