在C中,如何使用零值创建一个常量大小的`static`数组,但没有calloc?

Mic*_*hop 4 c stack allocation initialization

我目前在一个函数中有一些代码如下所示:

    static const int kFrameCountSample = 250;
    static float * samples = (float *)calloc(kFrameCountSample, sizeof(float));
Run Code Online (Sandbox Code Playgroud)

我喜欢样本数组只用一次归零calloc().

我也可以编写代码,因此samples在堆栈上分配.

    static const int kFrameCountSample = 250;
    static float samples[kFrameCountSample];
Run Code Online (Sandbox Code Playgroud)

但现在samples没有初始化为零值.如何在分配时初始化它?

Jac*_*ack 17

为了完整性(注意:这是C99 NOT C++):

重要的是要注意,如果定义并初始化长度k小于k - 1值的静态数组,则其余的将填充为零.因此:

static float samples[kFrameCountSample];
Run Code Online (Sandbox Code Playgroud)

......与以下内容相同:

static float samples[kFrameCountSample] = { 0 }; // Zero-fills.
Run Code Online (Sandbox Code Playgroud)

...并将零填充samples.此外,如果您执行以下操作:

static float samples[kFrameCountSample] = { 1, 2, 3 }; // Zero-fills elements of position 3 ... 250.
Run Code Online (Sandbox Code Playgroud)

...它将零填充初始化中未分配的其余元素samples.

备注:

  • 全局变量自动填充零(如果这是意图,则不需要初始化).
  • C99标准第6.7.8.10节中未初始化静态对象的标准说:

"如果没有显式初始化具有自动存储持续时间的对象,则其值是不确定的.如果未显式初始化具有静态存储持续时间的对象,则:

  • 如果它有指针类型,则将其初始化为空指针;
  • 如果它有算术类型,则初始化为(正或无符号)零;
  • 如果是聚合,则根据这些规则初始化(递归)每个成员;
  • 如果它是一个联合,则根据这些规则初始化(递归)第一个命名成员."

  • 这是错的.具有静态存储持续时间的对象(例如那些显式声明为`static`)的对象始终使用显式初始化程序进行初始化,如果没有给出,则为零. (3认同)
  • 我知道,我的评论适用于C.这在C99标准的§6.7.8中定义. (2认同)

caf*_*caf 7

您提供的代码:

static const int kFrameCountSample = 250;
static float samples[kFrameCountSample];
Run Code Online (Sandbox Code Playgroud)

无效C.具有静态存储持续时间的对象不能具有可变修改类型.另一方面,这将是有效的:

#define kFrameCountSample 250
static float samples[kFrameCountSample];
Run Code Online (Sandbox Code Playgroud)

这在文件范围或功能范围内有效.在这两种情况下,阵列samples都具有静态存储持续时间,这意味着它在程序的整个生命周期中都存在,并且在程序启动时仅初始化一次.该唯一的区别是,如果它在一个函数,这个名字的范围samples被限制在它的声明块.在这两种情况下都不可能在堆栈上分配.

samples这里的数组零初始化的 - 具有静态存储持续时间的对象永远不会被初始化.如果未提供显式初始值设定项,则将它们初始化为适当类型的零.

如果你这样做要保存在栈上的数组-也就是说,当进入创建一个包含声明的功能和销毁时退出函数,什么C调用自动存储时间 -那么你必须声明它的函数内部,省略static关键字并添加一个显式初始值设定项:

float samples[kFrameCountSample] = { 0 };
Run Code Online (Sandbox Code Playgroud)

(在这种情况下kFrameCountSample,不需要是一个宏,它可以是一个static const int如果你想要的).

{ 0 }无论数组的大小是多少都是单一的,因为C中的对象永远不会被部分初始化 - 如果初始化数组或结构的任何子对象,其余的子对象被初始化为适当类型的零,就像具有静态存储持续时间的对象.

  • @MichaelBishop:如果添加 `-pedantic` 选项,您将看到警告“*可变长度数组折叠为常量数组作为扩展*” (2认同)