问题描述
请谁能帮助我为什么符号常量的这种定义会产生函数内以下静态变量的错误定义: 错误:“变量”的存储大小不是恒定的
#define SAMPLE_RATE 200 /* Sample rate in Hz. */
#define MS_PER_SAMPLE ( (double) 1000/ (double) SAMPLE_RATE)
#define MS10 ((int) (10/ MS_PER_SAMPLE + 0.5))
#define MS25 ((int) (25/MS_PER_SAMPLE + 0.5))
#define MS30 ((int) (30/MS_PER_SAMPLE + 0.5))
#define MS80 ((int) (80/MS_PER_SAMPLE + 0.5))
#define MS95 ((int) (95/MS_PER_SAMPLE + 0.5))
#define MS100 ((int) (100/MS_PER_SAMPLE + 0.5))
#define MS125 ((int) (125/MS_PER_SAMPLE + 0.5))
#define MS150 ((int) (150/MS_PER_SAMPLE + 0.5))
#define MS160 ((int) (160/MS_PER_SAMPLE + 0.5))
#define MS175 ((int) (175/MS_PER_SAMPLE + 0.5))
#define MS195 ((int) (195/MS_PER_SAMPLE + 0.5))
#define MS200 ((int) (200/MS_PER_SAMPLE + 0.5))
#define MS220 ((int) (220/MS_PER_SAMPLE + 0.5))
#define MS250 ((int) (250/MS_PER_SAMPLE + 0.5))
#define MS300 ((int) (300/MS_PER_SAMPLE + 0.5))
#define MS360 ((int) (360/MS_PER_SAMPLE + 0.5))
#define MS450 ((int) (450/MS_PER_SAMPLE + 0.5))
#define MS1000 SAMPLE_RATE
#define MS1500 ((int) (1500/MS_PER_SAMPLE))
#define DERIV_LENGTH MS10
#define LPBUFFER_LGTH ((int) (2*MS25))
#define HPBUFFER_LGTH MS125#define WINDOW_WIDTH MS80 // Moving window integration width.
#define FILTER_DELAY (int) (((double) DERIV_LENGTH/2) + ((double) LPBUFFER_LGTH/2 - 1) + (((double) HPBUFFER_LGTH-1)/2) + PRE_BLANK) // filter delays plus 200 ms blanking delay
#define DER_DELAY WINDOW_WIDTH + FILTER_DELAY + MS100
int lpfilt( int datum,int init)
{
static long y1 = 0,y2 = 0 ;
static int data[MS_PER_SAMPLE],ptr = 0 ;
.....
int lpfilt( int datum,int init)
{
static int data[MS_PER_SAMPLE],ptr = 0 ;
....
int hpfilt( int datum,int init )
{
static int data[HPBUFFER_LGTH],ptr = 0 ;
...
int deriv1(int x,int init)
{
static int derBuff[DERIV_LENGTH],derI = 0 ;
...
int deriv2(int x,derI = 0 ;
...
int mvwint(int datum,int init)
{
static int data[WINDOW_WIDTH],ptr = 0 ;
...
我不知道问题可能是什么,无论我是否用 (int) 重新输入计算结果,它仍然会产生错误。符号常量定义中是否不允许重新输入?
解决方法
此清单常量中使用的表达式
#define MS_PER_SAMPLE ( (double) 1000/ (double) SAMPLE_RATE)
具有 double 类型。
它不是整数常量表达式。
因此,您不能将此清单常量用作数组的大小,例如在此声明中。
static int data[MS_PER_SAMPLE],ptr = 0 ;
您可以定义常量,例如
#define MS_PER_SAMPLE ( ( int ) ( 1000.0 / SAMPLE_RATE ) )
或者按原样保持清单常量声明
static int data[( int )MS_PER_SAMPLE],ptr = 0 ;
,
为什么在 C 语言中静态定义变量在编译时会失败?
您不能在常量中使用 + 0.5
。研究如何仅使用整数来舍入整数。
数组大小必须是一个常量表达式。来自cppreference constant expression:
整数常量表达式是仅由
组成的表达式- [...其他要点....]
- 浮动常量,但前提是它们立即用作转换为整数类型的操作数
double
值 0.5
不是“立即转换”(如 (int)0.5
),而是与运算符 +
一起使用以添加 int
.因此错误。
查看您的代码,概念验证可能如下所示:
// the simplest based on https://stackoverflow.com/questions/2422712/rounding-integer-division-instead-of-truncating
// but see also https://elixir.bootlin.com/linux/v4.17/source/include/linux/kernel.h#L132
#define DIV_ROUND(x,d) ((x + (d / 2)) / d)
#define SAMPLE_RATE 200 /* Sample rate in Hz. */
#define MS_PER_SAMPLE (1000 / SAMPLE_RATE)
#define MS125 DIV_ROUND(125,MS_PER_SAMPLE)
#define HPBUFFER_LGTH MS125
static int data[HPBUFFER_LGTH];
因为我看到 (int)
在您的代码中随处可见,所以现在是阅读 types of integer constants 和 conversions 的好时机。因为您使用的是宏,所以一定要了解 macro pitfalls。
KamilCuk 是对的,常量 0.5 在我的符号常量中无效。将 0.5 更改为 1/2 并将所有强制转换为 (double) 解决了该问题。非常感谢。