C中函数内部的静态变量初始化

C中函数内部的静态变量初始化,c,variables,static,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 =

考虑以下函数

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

}
int16读取输入(无效)
{
静态int32_t previous_input=read_encoder();//一些阈值)
一些动作();
上一次输入=当前输入;
//更多的代码+返回语句
}
由于该变量未初始化为编译时常量,因此我无法无错误地声明它

1) 该变量未在程序中的任何其他位置使用。因此,没有必要将其作为一个全局变量

2) 前一个功能需要初始化为当前输入,否则在初始运行期间,由于编码器连接到当前输入,当前输入和前一个输入之间的差异可能会非常大(无法判断编码器值在哪里,这取决于用户在关闭之前旋转了多少)。这将导致其他功能的错误触发

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

注意:此问题是复杂程序的一部分,我已对其进行了简化以避免复杂性。如果问题中存在任何歧义,请告知我

如果小心使用额外变量,您可以:

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;
}
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;

    // ...
}

更新:

如果
current\u input
来自
read\u encoder
,这里有一个清理版本,可以防止第一次重复读取

另外,最初,我使用了一个额外的标志变量,如果没有越界值,这是必要的。但是,我已经包括了第二个版本,它使用单个变量稍微快一点(如果不太安全):

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;
}
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;

    // ...
}

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

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;
}
是否有任何方法可以在函数中声明一个静态变量并将其初始化为与上面给出的示例类似的值

我看到了另一个问题,并提出了一个解决这两个问题的想法

减法运算溢出

if (previous_input - current_input > SOME_THRESHLD)  // OF possible
给定
以前的\u输入,当前的\u输入可以独立地是232中的任何一个,差异大约有233个不同的结果。如果
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

另一方面,如果不是所有232个组合都可能,那么减法和比较在32位数学中非常适合,那么使用保留值,并简单地检测它来执行初始化

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

我喜欢别人建议的
静态
独立标志的想法。但我想提供另一种方法


IAC,code,一般来说,需要使用
先前的\u输入-当前的\u输入进行保护

我不清楚为什么静态在这里很重要。除了Craig的好答案之外,您还可以将
先前的\u输入
初始化为
读取编码器
永远不会返回的值。例如,如果
读取编码器
返回一个数字在0和1023之间,然后将
previous_input
初始化为-1可使代码检测到以前没有输入。@DaveNewton:-我使用previous_input的唯一位置是在read_input函数内,它需要在函数调用之间保留值将previous_input替换为指示“not initialized”w的值我会解决我的问题。但我还有一个问题在这一点上并不重要-如果前一个输入存储的值是-SOME\u LIMIT到+SOME\u LIMIT怎么办。例如,它连接到一个连续旋转旋转编码器。在这种情况下,SOME\u LIMIT值由存储该值的数据类型确定,并且只有当超出了数据类型限制。您可能想补充一点,可能溢出的原因是这些是有符号整数。@Germanner我基本同意。但是,如果类型是有符号或无符号整数,则可能会出现数学溢出。当然,对于无符号的of,不会产生UB,但它是数学上的answ使用
上一个\u输入-当前\u输入>一些\u阈值
。是的,我知道这一点。我只是认为OP可能无法理解这些溢出发生的原因以及后果。我想不是每个人都容易理解为什么INT32_MIN-INT32_MAX需要33位数学。