在C中声明和初始化数组

有没有办法先声明然后在C中初始化数组?

到目前为止,我一直在初始化这样的数组:

int myArray[SIZE] = {1,2,3,4....};

但是我需要做这样的事情

int myArray[SIZE];

myArray = {1,2,3,4....};
Dave H asked 2020-01-13T04:54:26Z
8个解决方案
32 votes

在C99中,您可以将复合文字与memcpy结合使用

memcpy(myarray, (int[]) { 1, 2, 3, 4 }, sizeof myarray);

(假设源的大小和目标的大小相同)。

在C89 / 90中,您可以通过声明一个附加的“源”数组来模拟

const int SOURCE[SIZE] = { 1, 2, 3, 4 }; /* maybe `static`? */
int myArray[SIZE];
...
memcpy(myarray, SOURCE, sizeof myarray);
AnT answered 2020-01-13T04:54:44Z
13 votes

不,您不能在一个语句中将它们设置为任意值(除非作为声明的一部分完成)。

您可以使用代码执行此操作,例如:

myArray[0] = 1;
myArray[1] = 2;
myArray[2] = 27;
:
myArray[99] = -7;

或(如果有公式):

for (int i = 0; i < 100; i++) myArray[i] = i + 1;

另一种可能性是保留声明时设置的一些模板,并使用它们来初始化数组,例如:

static const int onceArr[]  = {  0,  1,  2,  3,  4,..., 99};
static const int twiceArr[] = {  0,  2,  4,  6,  8,...,198};
:
int myArray[7];
:
memcpy (myArray, twiceArr, sizeof (myArray));

这具有(最有可能)更快的优点,并允许您创建比模板小的数组。 在必须快速重新初始化数组但将其初始化为特定状态的情况下,我使用了此方法(如果状态全为零,则只使用memcpy)。


您甚至可以将其本地化为初始化函数:

void initMyArray (int *arr, size_t sz) {
    static const int template[] = {2, 3, 5, 7, 11, 13, 17, 19, 21, ..., 9973};
    memcpy (arr, template, sz);
}
:
int myArray[100];
initMyArray (myArray, sizeof(myArray));

静态数组(几乎可以肯定)将在编译时创建,因此不会有运行时开销,并且memcpy应该令人眼花fast乱,可能比1,229赋值语句快,但您输入的类型肯定更少:-) 。

paxdiablo answered 2020-01-13T04:55:31Z
4 votes

有没有办法先声明   然后在C中初始化数组?

有! 但不使用您描述的方法。

您不能使用逗号分隔的列表进行初始化,这仅在声明中允许。 但是,您可以使用...进行初始化

myArray[0] = 1;
myArray[1] = 2;
...

要么

for(int i = 1; i <= SIZE; i++)
{
  myArray[i-1] = i;
}
Jacob answered 2020-01-13T04:56:05Z
2 votes

这是AndreyT接受的答案的附录,其中包括Nyan对不匹配的数组大小的评论。 我不同意他们将第五个元素自动设置为零的观点。 它应该是5-1,2,3,4之后的数字。 因此,当我们尝试复制不同大小的数组时,我建议对memcpy()进行包装,以产生编译时错误:

#define Memcpy(a,b) do {                    /* copy arrays */       \
    ASSERT(sizeof(a) == sizeof(b) &&        /* a static assert */   \
           sizeof(a) != sizeof((a) + 0));   /* no pointers */       \
    memcpy((a), (b), sizeof (b));           /* & unnecesary */      \
    } while (0)                             /* no return value */

如果您的数组长度为1,则此宏将生成编译时错误。这也许是一个功能。

因为我们使用的是宏,所以C99复合文字似乎需要额外的一对括号:

Memcpy(myarray, ((int[]) { 1, 2, 3, 4 }));

这里的ASSERT()是一个“静态断言”。 如果您还没有自己的设备,那么我将在许多平台上使用以下工具:

#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum {EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
#define ASSERTM(e,m) /* version of ASSERT() with message */ \
    enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
Joseph Quinsey answered 2020-01-13T04:56:39Z
1 votes

为什么在声明时不能初始化?

您正在使用哪个C编译器? 它支持C99吗?

如果它确实支持C99,则可以在需要的地方声明该变量,并在声明它时对其进行初始化。

我不这样做的唯一借口是,因为您需要声明它,但是在使用它之前先退出,所以初始化程序将被浪费。 但是,我怀疑任何这样的代码都没有应有的清晰组织,并且可以编写,因此这不是问题。

Jonathan Leffler answered 2020-01-13T04:57:13Z
0 votes

声明一次之后,没有什么特别的方法可以初始化数组。

只有三个选项:

1.)在不同的行中初始化它们:

int array[SIZE];

array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 4;
//...
//...
//...

但这不是我想要的。

2.)使用for或while循环初始化它们:

for (i = 0; i < MAX ; i++)  {
    array[i] = i;
}

这是实现目标的最佳途径。

3)如果您需要在一行内初始化数组,则必须至少定义一个带有初始化的数组。 然后将其复制到目标数组,但我认为这样做没有任何好处,在这种情况下,您应该在一行内定义和初始化数组。

我能问你为什么特别想这样做吗???

Kumar Alok answered 2020-01-13T04:58:04Z
0 votes

OP从问题中遗漏了一些关键信息,只在评论中添加了答案。

我需要在声明后进行初始化,因为会有所不同   根据条件,我的意思是这样的   myArray [SIZE]; if(condition1){myArray {x1,x2,x3,...}}其他   if(condition2){myArray {y1,y2,y3,...}}。 。 等等...

考虑到这一点,所有可能的数组无论如何都需要存储到数据中,因此不需要(或不需要)memcpy,只需要一个指针和一个2d数组即可。

//static global since some compilers build arrays from instruction data
//... notably not const though so they can later be modified if needed
#define SIZE 8
static int myArrays[2][SIZE] = {{0,1,2,3,4,5,6,7},{7,6,5,4,3,2,1,0}};

static inline int *init_myArray(_Bool conditional){
  return myArrays[conditional];
}

// now you can use:
//int *myArray = init_myArray(1 == htons(1)); //any boolean expression

非内联版本在x86_64上提供了此生成的程序集:

init_myArray(bool):
        movzx   eax, dil
        sal     rax, 5
        add     rax, OFFSET FLAT:myArrays
        ret
myArrays:
        .long   0
        .long   1
        .long   2
        .long   3
        .long   4
        .long   5
        .long   6
        .long   7
        .long   7
        .long   6
        .long   5
        .long   4
        .long   3
        .long   2
        .long   1
        .long   0

对于其他条件/数组,只需将myArrays中的2更改为所需的数字,并使用类似的逻辑即可获取指向正确数组的指针。

technosaurus answered 2020-01-13T04:58:42Z
0 votes

初始化后不可能一次将所有值分配给数组。最好的选择是使用循环。

for(i=0;i<N;i++)
{
     array[i] = i;
}

您可以硬编码并分配--array[0] = 1之类的值,依此类推。

如果已经将数据存储在数组中,则也可以使用Memcpy。

Tush_08 answered 2020-01-13T04:59:11Z
translate from https://stackoverflow.com:/questions/3137671/declaring-and-initializing-arrays-in-c