【问题标题】:Is there an alternative to Range Initialization of arrays in C?是否有替代 C 中数组的范围初始化的替代方法?
【发布时间】:2021-08-13 22:23:49
【问题描述】:

我相信这是一个简单的问题: 有没有办法在不使用循环的情况下用非零值初始化数组?

我知道的一种方法是使用范围初始化来用我想要的值初始化数组。 例如:

int main()
{
   /* Using Designated Range Initialization*/
   int my_array[10] = {[0 ... 3] = 5, [4 ... 7] = 15, [8 ... 9] = 30};
   /* Using Explicit initialization for each element */
   int other_array[10] = {5, 5, 5, 5, 15, 15, 15, 15, 30, 30};

   return 0;
}

但是,这种方法只是 GCC 编译器的扩展,而不是 ISO C 的一部分。所以考虑到系统之间可能存在不可移植性,有没有办法以类似的方式进行数组初始化?当然,不用循环。

另外,我正在寻找的方法只是超出了数组每个元素的显式初始化。

【问题讨论】:

  • 仅列出所有值就足够了:int my_array[10] = {5,5,5,5,15,15,15,15,15,30,30};?
  • 感谢您的回答!但如果它是一个非常大的数组,这可能是一项乏味的任务。
  • 是的。但是除了“替代方案”之外,您还没有说明您的确切要求是什么。因此,如果您有其他具体要求,那么建议您更新您的问题以这样说。
  • 确实!我将更新问题以使其更具限制性。

标签: c gcc designated-initializer


【解决方案1】:

代码需要显式初始化非零数组元素。

如果有模式可以使用宏魔法:

#define ONE(x) (x), (x)+1, (x)+2, (x)+3, (x)+4, (x)+5, (x)+6, (x)+7, (x)+8, (x)+9
#define TEN(x) ONE(x),ONE((x)+10),ONE((x)+20),ONE((x)+30),ONE((x)+40), \
    ONE((x)+50),ONE((x)+60),ONE((x)+70),ONE((x)+80),ONE((x)+90)

int main() {
  int count[100] = { TEN(1) };
  printf("%d %d\n", count[0], count[99] );
}

输出

1 100

OP 示例

#define X2(x) (x), (x)
// Note the nested macro
#define X4(x) X2(x), X2(x)
#define X8(x) X4(x), X4(x)
#define X10(x) X8(x), X2(x)
#define X16(x) X8(x), X8(x)
// ....


int main()
{
   int my_array[10] = { X4(5), X4(15), X2(30)};
   printf("%d %d\n", my_array[0], my_array[9] );
   return 0;
}

输出

5 30

【讨论】:

  • 问题中的例子你会如何使用它?
  • 多么有趣!我没有想到使用这种方式,但我会问与上面用户相同的问题。
  • 这是一个不错的方法。
  • 第一组宏名不是很清楚。也许他们应该被命名为TEN_FROM()TEN_BY_TEN_FROM()
  • 这是一个创造性的例子。这是实现它的好方法。
【解决方案2】:

唯一可移植的替代方法是明确列出它们。

int my_array[] = {
    5, 5, 5, 5,
    15, 15, 15, 15,
    30, 30
};

如果数组很大,这当然会很麻烦。在这种情况下,您可以使用bashawk 中的简单脚本来创建声明。它可以将其写入您与#include 合并的头文件中。

【讨论】:

  • 我不知道为此目的使用 awk 或 bash 脚本。提前感谢您的回答。
  • @onlyMinimum 使用awk/bash 生成.h 的想法很好。我会建议它(也使用perl/python)。您甚至可以用 C 编写生成器,尽管脚本/宏语言通常更方便。这将被称为宏编程(过去用于成熟的宏处理器(例如m4--另一种选择)),但现代术语是 metaprogramming
  • @CraigEstey,还没有达到那种编程知识水平,但这就是我想要达到的目标。
【解决方案3】:

来自 Barmar 的回答下的 cmets ...

@CraigEstey,还没有达到那种编程知识水平,但这就是我想要达到的目标。 – 最低限度

我猜的差不多——这就是我建议用 C 编写程序的原因。

不用担心......元编程是一个花哨/性感的术语,它可以非常简单地实现/使用。


为了帮助您入门或提供想法,这里有一个生成器示例程序(例如gen.c):

#include <stdio.h>

void
dorange(int lo,int hi,int val)
{

    for (;  lo <= hi;  ++lo)
        printf("%d, ",val);
}

int
main(void)
{
    printf("int myarray[10] = {\n");

    dorange(0,3,5);
    dorange(4,7,15);
    dorange(8,9,30);

    printf("\n");
    printf("};\n");

    return 0;
}

这是该程序的输出:

int myarray[10] = {
5, 5, 5, 5, 15, 15, 15, 15, 30, 30,
};

所以,如果您打算使用 Makefile 将输出放入 myarray.h

all: myprogram

# create the target program [after creating the generated file]
myprogram: myprogram.c myarray.h
    cc -o myprogram myprogram.c

# create the generated file
myarray.h: gen
    ./gen > myarray.h

# create the generator program
gen: gen.c
    cc -o gen gen.c

# clean up files ...
clean:
    rm -f gen myarray.h myprogram

这里是myprogram.c

#include <stdio.h>
#include "myarray.h"

int
main(void)
{

    for (int idx = 0;  idx < sizeof(myarray) / sizeof(myarray[0]);  ++idx)
        printf(" %d",myarray[idx]);

    printf("\n");

    return 0;
}

这是myprogram的输出:

 5 5 5 5 15 15 15 15 30 30

【讨论】:

  • 我喜欢这个实现!甚至更多地使用 shell 重定向运算符,我对此有更多经验。
猜你喜欢
  • 1970-01-01
  • 2022-01-01
  • 2013-08-08
  • 2021-03-24
  • 2010-09-20
  • 1970-01-01
  • 1970-01-01
  • 2013-08-08
相关资源
最近更新 更多