C

时间:2018-12-07 03:27:21

标签: c variables static

考虑以下功能

int16_t read_input(void)
{
   static int32_t previous_input = read_encoder(); // <--Not a compile time constant

   //Read current_input 

   if (previous_input - current_input > SOME_THRESHLD)
       some_action();

   previous_input = current_input;

   //some more code + return statement

}

由于未将变量初始化为编译时常数,因此我无法正确声明它。有两个原因使我希望将变量保留为函数内的静态变量

1)该变量未在程序中的其他任何地方使用。因此,无需将其保留为全局变量

2)需要将先前的功能初始化为当前输入,否则在初始运行期间,由于编码器连接到当前输入,因此当前输入和先前输入之间的差异可能会非常高(并且无法分辨出位置可能是编码器值,具体取决于用户在关闭之前旋转了多少)。这将导致其他功能的错误触发。

是否有任何方法可以在函数内部声明静态变量并将其初始化为类似于上面给出的示例的值?

注意:此问题是复杂程序的一部分,为了避免复杂性,我对其进行了简化。如果这个问题有任何歧义,请告诉我

3 个答案:

答案 0 :(得分:3)

如果您小心使用其他变量,可以可以

int16_t
read_input(void)
{
    static int32_t previous_input = 0;
    static int first_time = 1;

    if (first_time) {
        first_time = 0;
        previous_input = read_encoder();
    }

    // Read current_input

    if (previous_input - current_input > SOME_THRESHLD)
        some_action();

    previous_input = current_input;
}

更新:

如果 current_input来自read_encoder,这是一个清理的版本,可防止首次读取。

此外,最初,我使用了一个额外的标志变量,如果没有 no 超出范围值,则这是必需的。但是,我提供了第二个版本,该版本使用单个变量的速度稍快 [如果不太安全],

int16_t
read_input(void)
{
    static int32_t previous_input = 0;
    static int first_time = 0;
    int32_t current_input;

    // Read current_input
    current_input = read_encoder();

    if (first_time) {
        first_time = 0;
        previous_input = current_input;
    }

    if (previous_input - current_input > SOME_THRESHLD)
        some_action();

    previous_input = current_input;
}

#define OUT_OF_BOUNDS   -1

int16_t
read_input2(void)
{
    static int32_t previous_input = OUT_OF_BOUNDS;
    int32_t current_input;

    // Read current_input
    current_input = read_encoder();

    if (previous_input == OUT_OF_BOUNDS)
        previous_input = current_input;

    if (previous_input - current_input > SOME_THRESHLD)
        some_action();

    previous_input = current_input;

    // ...
}

答案 1 :(得分:2)

您可以首先将值设置为某个默认值,然后在首次调用该方法时,检查该值是否已初始化。如果没有,则将其初始化。

int16_t read_input(void)
{
   static int32_t previous_input = 0; // or a value indicating 'not initialised'
   if (previous_input == 0) previous_input = read_encoder();

   //Read current_input 

   if (previous_input - current_input > SOME_THRESHLD)
       some_action();

   previous_input - current_input;
}

答案 2 :(得分:2)

  

是否有任何方法可以在函数内部声明静态变量并将其初始化为类似于上面给出的示例的值?

我看到了另一个问题,并提出了一个解决方案。

减法溢出

if (previous_input - current_input > SOME_THRESHLD)  // OF possible

给定previous_input, current_input可以独立为2 32 中的任何一个,其差值大约有2 33 个不同的结果。使用int为32位时,代码可能会溢出(UB),并且无法唯一区分。在具有64位int的特殊平台上,可以很好地计算出差异,但是现在功能与32位平台有所不同。

考虑使用int64_t,因为需要33位以上的数学运算。

#define SPECIAL_BIG (INT64_MAX/2)
static int64_t previous_input = SPECIAL_BIG;
if (previous_input == SPECIAL_BIG) {
   previous_input = read_encoder();  // first time
}
...
if (previous_input - current_input > SOME_THRESHLD) {
    some_action();
  }
}
...
if (previous_input - current_input > SOME_THRESHLD)  // OF not possible

另一方面,如果不是所有2 32 组合都可能,并且减法和比较在32位数学运算中的拟合度很好,则使用保留值。 @user3386109并简单地检测到该内容即可执行初始化。

static int32_t previous_input = SPECIAL.
if (previous_input == SPECIAL) {
  previous_input = read_encoder();  // first time
}

我喜欢其他人建议的static分离标志的想法。但是想提供另一种方法。

通常,IAC代码需要使用previous_input - current_input进行OF保护