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

时间:2008-10-14 13:13:41

标签: c arrays initialization array-initialize

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

26 个答案:

答案 0 :(得分:1144)

除非该值为0(在这种情况下,您可以省略初始化程序的某些部分 并且相应的元素将初始化为0),没有简单的方法。

不要忽视明显的解决方案:

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。 这是not allowed C:

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

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

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

并且“0”并不一定意味着“所有位为零”,因此使用上述方法是 比memset()更好,更便携。 (浮点值将是 初始化为+0,指向空值的指针等。)

答案 1 :(得分:371)

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

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

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

答案 2 :(得分:171)

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

#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. */

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

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

宏名称可以协商。

答案 3 :(得分:61)

如果要确保显式初始化数组的每个成员,只需省略声明中的维度:

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

编译器将从初始化列表中推断出维度。不幸的是,对于多维数组,只能省略最外层的维度:

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

没问题,但是

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

不是。

答案 4 :(得分:47)

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

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

这样可以保持秩序井然有序,即使您碰巧无序地编写了一些枚举值。

有关此技术的更多信息,请参见herehere

答案 5 :(得分:21)

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...

改变数组大小的变化。

答案 6 :(得分:11)

你可以像上面详述的那样完成整个静态初始化器的事情,但是当你的数组大小改变时(当你的数组嵌入时,如果你没有添加适当的额外初始化器就会得到垃圾),它可能真的很糟糕。

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

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

答案 7 :(得分:7)

这是另一种方式:

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-Extensions

指定的内容

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

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

答案 8 :(得分:5)

对于初始化'普通'数据类型(如int数组),您可以使用括号表示法,但如果数组中仍有空格,它将在最后一个之后将值归零:

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

答案 9 :(得分:5)

略微诙谐的回答;写下声明

array = initial_value

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

答案 10 :(得分:4)

如果数组恰好是int或任何大小为int的内容,或者mem-pattern的大小恰好适合int(即全零或0xA5A5A5A5),最好的方法是使用memset()。< / p>

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

答案 11 :(得分:4)

int 数组[1024] = {[0 ... 1023] = 5};由于上述工作正常,但请确保...点之间没有空格

答案 12 :(得分:3)

There is a fast way to initialize array of any type with given value. It works very well with large arrays. Algorithm is as follows:

  • initialize first element of the array (usual way)
  • copy part which has been set into part which has not been set, doubling the size with each next copy operation

For $last_of_month = date("Y-m-t", strtotime($the_Date)); elements 1 000 000 array it is 4 times faster than regular loop initialization (i5, 2 cores, 2.3 GHz, 4GiB memory, 64 bits):

int

loop runtime 0.004248 [seconds]


memfill() runtime 0.001085 [seconds]

答案 13 :(得分:1)

  1. 如果您的数组声明为静态或全局,则为所有元素 在数组中已经有默认的默认值0。
  2. 有些编译器在调试模式下将数组的默认值设置为0。
  3. 很容易将默认设置为0: int array [10] = {0};
  4. 但是,对于其他值,您使用了memset()或loop;
  5. 例如:     int array [10];     memset(array,-1,10 * sizeof(int));

答案 14 :(得分:1)

<块引用>

方法一:

Optional<V>

正式的初始化技术。

<块引用>

方法二:

int a[5] = {3,3,3,3,3}; 

但值得注意的是

int a[100] = {0};

不会将所有值初始化为 1

这种专为0初始化的方式

如果你只是这样做

int a[10] = {1}; 

一些编译器倾向于采用垃圾值,因此它总是首选

int a[100];

答案 15 :(得分:1)

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

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

添加了奖励:代码实际上清晰可见:)

答案 16 :(得分:1)

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

#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

答案 17 :(得分:0)

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

它将给出o / p 5 5 5 5 5 5 ......直到整个数组的大小

答案 18 :(得分:0)

我知道用户Tarski以类似的方式回答了这个问题,但我补充了一些细节。原谅我的一些C因为我有点生气,因为我更倾向于想要使用C ++,但现在就这样了。

如果你提前知道阵列的大小......

#include <stdio.h>

typedef const unsigned int cUINT;
typedef unsigned int UINT;

cUINT size = 10;
cUINT initVal = 5;

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal );
void printArray( UINT* myArray ); 

int main() {        
    UINT myArray[size]; 
    /* Not initialized during declaration but can be
    initialized using a function for the appropriate TYPE*/
    arrayInitializer( myArray, size, initVal );

    printArray( myArray );

    return 0;
}

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal ) {
    for ( UINT n = 0; n < size; n++ ) {
        myArray[n] = initVal;
    }
}

void printArray( UINT* myArray ) {
    printf( "myArray = { " );
    for ( UINT n = 0; n < size; n++ ) {
        printf( "%u", myArray[n] );

        if ( n < size-1 )
            printf( ", " );
    }
    printf( " }\n" );
}

上面有一些警告;一个是UINT myArray[size];在声明时没有直接初始化,但是下一个代码块或函数调用会将数组的每个元素初始化为您想要的相同值。另一个警告是,你必须为你支持的每个initializing function写一个type,你还必须修改printArray()函数来支持这些类型。

您可以使用找到here的在线编辑器尝试此代码。

答案 19 :(得分:0)

对于延迟初始化(即类成员构造函数初始化),请考虑:

int a[4];

unsigned int size = sizeof(a) / sizeof(a[0]);
for (unsigned int i = 0; i < size; i++)
  a[i] = 0;

答案 20 :(得分:0)

回到过去(我并不是说这是一个好主意),我们将设置第一个元素,然后:

memcpy (&element [1], &element [0], sizeof (element)-sizeof (element [0]);

甚至不确定它是否会继续工作(这取决于memcpy的实现),但是它可以通过将初始元素重复复制到下一个元素而起作用-甚至适用于结构数组。

答案 21 :(得分:0)

如果您的意思是并行的,我认为将逗号运算符与表达式结合使用可以做到这一点:

a[1]=1, a[2]=2, ..., a[indexSize]; 

或者,如果您的意思是在单个结构中,则可以在for循环中进行:

for(int index = 0, value = 10; index < sizeof(array)/sizeof(array[0]); index++, value--)
  array[index] = index;

//请注意,参数列表中的逗号运算符不是上述并行运算符;

您可以初始化数组清理:

array[] = {1, 2, 3, 4, 5};

您可以调用malloc / calloc / sbrk / alloca / etc将固定的存储区域分配给对象:

int *array = malloc(sizeof(int)*numberOfListElements/Indexes);

并通过以下方式访问成员:

*(array + index)

等等。

答案 22 :(得分:0)

如果预先知道数组的大小,则可以使用Boost预处理程序C_ARRAY_INITIALIZE宏为您完成脏工作:

#include <boost/preprocessor/repetition/enum.hpp>
#define C_ARRAY_ELEMENT(z, index, name) name[index]
#define C_ARRAY_EXPAND(name,size) BOOST_PP_ENUM(size,C_ARRAY_ELEMENT,name)
#define C_ARRAY_VALUE(z, index, value) value
#define C_ARRAY_INITIALIZE(value,size) BOOST_PP_ENUM(size,C_ARRAY_VALUE,value)

答案 23 :(得分:0)

用零初始化 -

  char arr[1000] = { 0 };

最好用普通的“for循环”来初始化,而不是0。

  char arr[1000];
  for(int i=0; i<arr.size(); i++){
     arr[i] = 'A';
  }

答案 24 :(得分:-1)

我知道原始问题明确提到了C而不是C ++,但是如果您(像我一样)来到这里寻找C ++数组的解决方案,这是一个巧妙的窍门:

如果编译器支持link,则可以使用模板magic和std::index_sequence生成具有所需值的初始化列表。您甚至可以constexpr感觉像个老板:

#include <array>

/// [3]
/// This functions's only purpose is to ignore the index given as the second
/// template argument and to always produce the value passed in.
template<class T, size_t /*ignored*/>
constexpr T identity_func(const T& value) {
    return value;
}

/// [2]
/// At this point, we have a list of indices that we can unfold
/// into an initializer list using the `identity_func` above.
template<class T, size_t... Indices>
constexpr std::array<T, sizeof...(Indices)>
make_array_of_impl(const T& value, std::index_sequence<Indices...>) {
    return {identity_func<T, Indices>(value)...};
}

/// [1]
/// This is the user-facing function.
/// The template arguments are swapped compared to the order used
/// for std::array, this way we can let the compiler infer the type
/// from the given value but still define it explicitly if we want to.
template<size_t Size, class T>
constexpr std::array<T, Size> 
make_array_of(const T& value) {
    using Indices = std::make_index_sequence<Size>;
    return make_array_of_impl(value, Indices{});
}

// std::array<int, 4>{42, 42, 42, 42}
constexpr auto test_array = make_array_of<4/*, int*/>(42);
static_assert(test_array[0] == 42);
static_assert(test_array[1] == 42);
static_assert(test_array[2] == 42);
static_assert(test_array[3] == 42);
// static_assert(test_array[4] == 42); out of bounds

您可以查看fold expressions(在Wandbox上)

答案 25 :(得分:-1)

我在问题中看不到任何要求,因此解决方案必须是通用的:初始化未指定的可能多维数组,该数组是使用初始成员值从未指定的可能结构元素构建的:

#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