我在C中有一个大数组(不是c++,如果这有区别的话)。我想初始化相同值的所有成员。

我发誓我曾经知道一个简单的方法。在我的情况下,我可以使用memset(),但没有一种方法来做到这一点,这是建立在C语法?


当前回答

有一个快速的方法来初始化任何类型的数组与给定的值。它在大型阵列上工作得非常好。算法如下:

初始化数组的第一个元素(通常的方式) 将已设置的部分复制为未设置的部分,每次复制操作都将大小增加一倍


对于1 000 000个数组元素,它比常规循环初始化快4倍(i5, 2核,2.3 GHz, 4GiB内存,64位):

循环运行时间0.004248[秒]

Memfill()运行时间0.001085[秒]


#include <stdio.h>
#include <time.h>
#include <string.h>
#define ARR_SIZE 1000000

void memfill(void *dest, size_t destsize, size_t elemsize) {
   char   *nextdest = (char *) dest + elemsize;
   size_t movesize, donesize = elemsize;

   destsize -= elemsize;
   while (destsize) {
      movesize = (donesize < destsize) ? donesize : destsize;
      memcpy(nextdest, dest, movesize);
      nextdest += movesize; destsize -= movesize; donesize += movesize;
   }
}    
int main() {
    clock_t timeStart;
    double  runTime;
    int     i, a[ARR_SIZE];

    timeStart = clock();
    for (i = 0; i < ARR_SIZE; i++)
        a[i] = 9;    
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("loop runtime %f [seconds]\n",runTime);

    timeStart = clock();
    a[0] = 10;
    memfill(a, sizeof(a), sizeof(a[0]));
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("memfill() runtime %f [seconds]\n",runTime);
    return 0;
}

其他回答

对于静态初始化具有相同值的大型数组,不需要多次复制粘贴,你可以使用宏:

#define VAL_1X     42
#define VAL_2X     VAL_1X,  VAL_1X
#define VAL_4X     VAL_2X,  VAL_2X
#define VAL_8X     VAL_4X,  VAL_4X
#define VAL_16X    VAL_8X,  VAL_8X
#define VAL_32X    VAL_16X, VAL_16X
#define VAL_64X    VAL_32X, VAL_32X

int myArray[53] = { VAL_32X, VAL_16X, VAL_4X, VAL_1X };

如果需要更改值,则只能在一个位置进行替换。

编辑:可能有用的扩展

(乔纳森·莱弗勒提供)

你可以很容易地概括这一点:

#define VAL_1(X) X
#define VAL_2(X) VAL_1(X), VAL_1(X)
/* etc. */

可以使用以下命令创建变量:

#define STRUCTVAL_1(...) { __VA_ARGS__ }
#define STRUCTVAL_2(...) STRUCTVAL_1(__VA_ARGS__), STRUCTVAL_1(__VA_ARGS__)
/*etc */ 

这适用于结构或复合数组。

#define STRUCTVAL_48(...) STRUCTVAL_32(__VA_ARGS__), STRUCTVAL_16(__VA_ARGS__)

struct Pair { char key[16]; char val[32]; };
struct Pair p_data[] = { STRUCTVAL_48("Key", "Value") };
int a_data[][4] = { STRUCTVAL_48(12, 19, 23, 37) };

宏名称可以协商。

如果数组恰好是int或int大小的任何东西,或者你的mempattern的大小恰好符合int的精确时间(即全部为零或0xA5A5A5A5),最好的方法是使用memset()。

否则,在循环中调用memcpy()移动索引。

如果你的编译器是GCC,你可以使用以下“GNU扩展”语法:

int array[1024] = {[0 ... 1023] = 5};

查看详细描述: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html

有一个快速的方法来初始化任何类型的数组与给定的值。它在大型阵列上工作得非常好。算法如下:

初始化数组的第一个元素(通常的方式) 将已设置的部分复制为未设置的部分,每次复制操作都将大小增加一倍


对于1 000 000个数组元素,它比常规循环初始化快4倍(i5, 2核,2.3 GHz, 4GiB内存,64位):

循环运行时间0.004248[秒]

Memfill()运行时间0.001085[秒]


#include <stdio.h>
#include <time.h>
#include <string.h>
#define ARR_SIZE 1000000

void memfill(void *dest, size_t destsize, size_t elemsize) {
   char   *nextdest = (char *) dest + elemsize;
   size_t movesize, donesize = elemsize;

   destsize -= elemsize;
   while (destsize) {
      movesize = (donesize < destsize) ? donesize : destsize;
      memcpy(nextdest, dest, movesize);
      nextdest += movesize; destsize -= movesize; donesize += movesize;
   }
}    
int main() {
    clock_t timeStart;
    double  runTime;
    int     i, a[ARR_SIZE];

    timeStart = clock();
    for (i = 0; i < ARR_SIZE; i++)
        a[i] = 9;    
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("loop runtime %f [seconds]\n",runTime);

    timeStart = clock();
    a[0] = 10;
    memfill(a, sizeof(a), sizeof(a[0]));
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("memfill() runtime %f [seconds]\n",runTime);
    return 0;
}

我看到了一些使用这种语法的代码:

char* array[] = 
{
    [0] = "Hello",
    [1] = "World"
};   

它变得特别有用的地方是当你创建一个使用枚举作为索引的数组时:

enum
{
    ERR_OK,
    ERR_FAIL,
    ERR_MEMORY
};

#define _ITEM(x) [x] = #x

char* array[] = 
{
    _ITEM(ERR_OK),
    _ITEM(ERR_FAIL),
    _ITEM(ERR_MEMORY)
};   

这使事情保持有序,即使您碰巧把一些枚举值写成了无序的顺序。

关于这项技术的更多信息可以在这里和这里找到。