如何初始化一个数组的所有成员为相同的值?

我在C中有一个大数组(不是C ++,如果这有所作为)。 我想将所有成员初始化为相同的值。 我可以发誓我曾经知道一个简单的方法来做到这一点。 我可以在我的情况下使用memset() ,但没有办法做到这一点是内置到C语法?

除非这个值是0(在这种情况下,你可以忽略初始化器的某个部分,相应的元素将被初始化为0),但是没有简单的方法。

不要忽视这个显而易见的解决scheme,

 int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }; 

具有缺失值的元素将被初始化为0:

 int myArray[10] = { 1, 2 }; // initialize to 1,2,0,0,0... 

所以这会将所有元素初始化为0:

 int myArray[10] = { 0 }; // all elements 0 

在C ++中,一个空的初始化列表也会将每个元素初始化为0.对于C:

 int myArray[10] = {}; // all elements 0 in C++ 

请记住,如果没有指定初始化程序,则具有静态存储持续时间的对象将初始化为0:

 static int myArray[10]; // all elements 0 

而且这个“0”并不一定意味着“all-bits-zero”,所以使用上述方法比memset()更好,更方便。 (浮点值将被初始化为+0,指向空值的指针等)

如果你的编译器是GCC,你可以使用下面的语法:

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

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

要使用相同的值静态初始化一个大数组,而没有多个复制粘贴,可以使用macros:

 #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 }; 

如果您需要更改值,则必须在一个地方进行更换。

编辑:可能有用的扩展

( Jonathan Leffler提供 )

你可以很容易地概括这个:

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

可以使用以下方法创build变体:

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

与结构或复合arrays一起工作。

 #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) }; 

macros名称是可协商的。

如果你想确保数组中的每一个成员都被明确地初始化,那么就省略声明中的维度:

 int myArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

编译器将从初始化程序列表中推导出维度。 不幸的是,对于multidimensional array,只有最外层的维度可能被省略:

 int myPoints[][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} }; 

是的,但是

 int myPoints[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} }; 

不是。

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

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

如果你正在创build一个使用枚举作为索引的数组,那么它变得特别有用:

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

这使得事情保持有序,即使您碰巧写出了一些乱序的枚举值。

有关这种技术的更多信息可以在这里和这里find。

 int i; for (i = 0; i < ARRAY_SIZE; ++i) { myArray[i] = VALUE; } 

我认为这比

 int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5... 

增加数组更改的大小。

你可以像上面详细描述的那样完成整个静态初始化器的工作,但是当你的数组大小发生变化的时候(如果你没有添加适当的额外的初始化器,你会得到垃圾),这可能是一个真正的失败者。

memset为您提供了一个运行时命中的工作,但没有正确完成代码大小不受数组大小更改的影响。 在几乎所有情况下,当数组大于比如说几十个元素时,我都会使用这个解决scheme。

如果数组是静态声明是非常重要的,我会编写一个程序来为我编写程序,并使其成为构build过程的一部分。

这是另一种方式:

 static void unhandled_interrupt(struct trap_frame *frame, int irq, void *arg) { //this code intentionally left blank } static struct irqtbl_s vector_tbl[XCHAL_NUM_INTERRUPTS] = { [0 ... XCHAL_NUM_INTERRUPTS-1] {unhandled_interrupt, NULL}, }; 

看到:

C-扩展

指定inits

然后问这个问题:什么时候可以使用C扩展?

上面的代码示例位于embedded式系统中,不会看到来自其他编译器的光。

对于初始化“普通”数据types(如int数组),可以使用括号表示法,但是如果数组中还有空格,则会将最后一个值归零:

 // put values 1-8, then two zeroes int list[10] = {1,2,3,4,5,6,7,8}; 

一个轻微的舌头在颊的答案; 写声明

 array = initial_value 

用你最喜欢的支持数组的语言(我的是Fortran,但还有很多其他语言),并将它链接到你的C代码。 你可能想把它包装起来成为一个外部函数。

有一个快速的方法来初始化具有给定值的任何types的数组。 它对于大型数组非常有效。 algorithm如下:

  • 初始化数组的第一个元素(通常的方式)
  • 复制已经被设定的部分,没有被设定的部分,与下一个复制操作一起倍增大小

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

loop runtime 0.004248 [seconds]

memfill() runtime 0.001085 [seconds]


 #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; } 

如果数组恰好是int或int大小的任何值,或者你的mem-pattern的大小符合int的整数(即全零或0xA5A5A5A5),最好的办法是使用memset() 。

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

你可以使用memset函数。

 void *memset(void *array, int value, unsigned sizeofarray); 

没有人提到索引顺序来访问初始化数组的元素。 我的示例代码将给出一个说明性的例子。

 #include <iostream> void PrintArray(int a[3][3]) { std::cout << "a11 = " << a[0][0] << "\t\t" << "a12 = " << a[0][1] << "\t\t" << "a13 = " << a[0][2] << std::endl; std::cout << "a21 = " << a[1][0] << "\t\t" << "a22 = " << a[1][1] << "\t\t" << "a23 = " << a[1][2] << std::endl; std::cout << "a31 = " << a[2][0] << "\t\t" << "a32 = " << a[2][1] << "\t\t" << "a33 = " << a[2][2] << std::endl; std::cout << std::endl; } int wmain(int argc, wchar_t * argv[]) { int a1[3][3] = { 11, 12, 13, // The most 21, 22, 23, // basic 31, 32, 33 }; // format. int a2[][3] = { 11, 12, 13, // The first (outer) dimension 21, 22, 23, // may be omitted. The compiler 31, 32, 33 }; // will automatically deduce it. int a3[3][3] = { {11, 12, 13}, // The elements of each {21, 22, 23}, // second (inner) dimension {31, 32, 33} }; // can be grouped together. int a4[][3] = { {11, 12, 13}, // Again, the first dimension {21, 22, 23}, // can be omitted when the {31, 32, 33} }; // inner elements are grouped. PrintArray(a1); PrintArray(a2); PrintArray(a3); PrintArray(a4); // This part shows in which order the elements are stored in the memory. int * b = (int *) a1; // The output is the same for the all four arrays. for (int i=0; i<9; i++) { std::cout << b[i] << '\t'; } return 0; } 

输出是:

 a11 = 11 a12 = 12 a13 = 13 a21 = 21 a22 = 22 a23 = 23 a31 = 31 a32 = 32 a33 = 33 a11 = 11 a12 = 12 a13 = 13 a21 = 21 a22 = 22 a23 = 23 a31 = 31 a32 = 32 a33 = 33 a11 = 11 a12 = 12 a13 = 13 a21 = 21 a22 = 22 a23 = 23 a31 = 31 a32 = 32 a33 = 33 a11 = 11 a12 = 12 a13 = 13 a21 = 21 a22 = 22 a23 = 23 a31 = 31 a32 = 32 a33 = 33 11 12 13 21 22 23 31 32 33 
  1. 如果数组声明为静态或全局的,则数组中的所有元素都具有默认的默认值0。
  2. 一些编译器在debugging模式下将数组的默认值设置为0。
  3. 将default设置为0很容易:int array [10] = {0};
  4. 但是,对于其他值,您可以使用memset()或循环;

例如:int array [10]; memset(array,-1,10 * sizeof(int));

通过所有的喋喋不休,简短的回答是,如果你在编译时打开优化,你将不会做得比这更好:

 int i,value=5,array[1000]; for(i=0;i<1000;i++) array[i]=value; 

额外的奖金:代码实际上是清晰的:)

 #include<stdio.h> int main(){ int i,a[50]; for (i=0;i<50;i++){ a[i]=5;// set value 5 to all the array index } for (i=0;i<50;i++) printf("%d\n",a[i]); return 0; } 

它会给出5/5 5 5 5 5 / …直到整个arrays的大小

我在这个问题中没有看到任何要求,所以解决scheme必须是通用的:初始化一个未指定的可能的multidimensional array,这个multidimensional array是由未指定的可能结构元素构build的,

 #include <string.h> void array_init( void *start, size_t element_size, size_t elements, void *initval ){ memcpy( start, initval, element_size ); memcpy( (char*)start+element_size, start, element_size*(elements-1) ); } // testing #include <stdio.h> struct s { int a; char b; } array[2][3], init; int main(){ init = (struct s){.a = 3, .b = 'x'}; array_init( array, sizeof(array[0][0]), 2*3, &init ); for( int i=0; i<2; i++ ) for( int j=0; j<3; j++ ) printf("array[%i][%i].a = %i .b = '%c'\n",i,j,array[i][j].a,array[i][j].b); } 

结果:

 array[0][0].a = 3 .b = 'x' array[0][1].a = 3 .b = 'x' array[0][2].a = 3 .b = 'x' array[1][0].a = 3 .b = 'x' array[1][1].a = 3 .b = 'x' array[1][2].a = 3 .b = 'x' 

编辑: start+element_size改为(char*)start+element_size