当前位置:  开发笔记 > 前端 > 正文

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

如何解决《如何将数组的所有成员初始化为相同的值?》经验,为你挑选了11个好方法。

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



1> aib..:

除非该值为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. C 不允许这样做:

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

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

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

而"0"并不一定意味着"所有位为零",因此使用上述内容比memset()更好,更便携.(浮点值将初始化为+0,指向空值的指针等)


查看第6.7.8节C99标准的初始化,似乎不允许使用空的初始化列表.
通过C++标准阅读,你也可以做int array [10] = {}; 初始化为零.我没有C标准来检查这是否也是有效的C.
@CetinSert:在该评论中,您是唯一声称所有元素都设置为-1的人.这个答案正确地声称所有未指定的元素都设置为零.您的代码结果与此声明一致.
@CetinSert:你的意思是什么不起作用?它正是这个答案所说的应该做的.它没有执行代码中的注释所说的内容,但该注释是错误的.
C99有很多很好的结构和数组初始化功能; 它没有的一个功能(但Fortran IV,1966,有)是一种为数组重复特定初始化器的方法.
@akofink:在下面查看qrdl的答案.这是GCC扩展.

2> qrdl..:

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

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

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


@CetinSert编译器必须将65536`int`s添加到静态数据中,这是256 K - 正是您观察到的大小增加.
更好的是:"int array [] = {[0 ... 1023] = 5}",数组的大小将自动设置为1024,修改起来更容易,更安全.
@CetinSert我为什么要这样?它是标准编译器行为,不是特定于指定的初始化程序.如果你静态初始化65536`int`s,比如`int foo1 = 1,foo2 = 1,...,foo65536 = 1;`你将获得相同的大小增加.
并且该语法导致编译的二进制文件的文件大小大幅增加.对于N = 65536(而不是1024),我的二进制文件从15 KB跳到270 KB!
@Francois或2d数组,`bool array [] [COLS] = {[0 ... ROWS-1] [0 ... COLS-1] = true}`,虽然我不确定它是否更具可读性比完整的形式.
我想当你说`gcc`时它也适用于`g ++`.

3> mouviciel..:

要静态初始化具有相同值的大型数组,而不使用多个复制粘贴,您可以使用宏:

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

宏名称可以协商.


如果数据必须是可ROM的,则不能使用memset.
我只会在极端情况下考虑这一点,当然memset是表达它的更优雅的方式.
预处理器实际上会从#defines生成代码.使用更大的数组维度,可执行文件的大小 但绝对+的想法;)
@Alcott,在旧计算机上,仍然在许多嵌入式系统上,代码最终放在[EPROM](http://en.wikipedia.org/wiki/EPROM"维基百科上的EPROM解释")或[ROM](http)中://en.wikipedia.org/wiki/Read-only_memory"维基百科的ROM解释").ROM-able也意味着,在嵌入式系统中,"代码放入闪存",因为它具有大致相同的含义,即内存不能写入运行时.即memset或任何其他更新或更改内存的指令都不能使用.但是,常量可以在程序启动之前表达,闪烁或ROM编辑.
@ u0b34a0f6ae:请记住,如果`VAL_1X`不是单个整数而是列表,也可以使用此方法.与Amigable状态一样,这也是您想要定义EEPROM或闪存的初始值的嵌入式系统的方法.在这两种情况下,你都不能使用`memset()`.
memset用char初始化.它不能用于将int数组初始化为42之类的值.值0可用于初始化为零.值-1可用于将数组初始化为-1.
您可以使用#define VAL_1(X)X和#define VAL_2(X)VAL_1(X),VAL_1(X)等轻松地对此进行概括。可以使用#define STRUCTVAL_1(... } {__VA_ARGS__}`和`#define STRUCTVAL_2(...)STRUCTVAL_1(__ VA_ARGS__),STRUCTVAL_1(__ VA_ARGS __)`等适用于结构或复合数组的对象。#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)};`—宏名称可以协商。

4> Frank Szczer..:

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

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

不是.


不.您省略了最内层的维度,这是不允许的.这将给出编译器错误.
初始化器和长度推断均在C99中引入.
@Palec:从标准C之前的日子开始就没有 - 长度推断(自K&R第1版发布以来,可能还需要一段时间).指定的初始化程序在C99中是新的,但这不是使用指定的初始化程序.

5> abelenky..:

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

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

这样可以使事情保持正常,即使您碰巧无序地编写了一些枚举值.

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


这是C99初始化程序语法,已经被其他一些答案所涵盖.您可以有效地将声明声明为`char const*array [] = {...};`甚至`char const*const array [] = {...};`,不是吗?

6> Tarski..:
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...

加入数组大小的变化.


@Benson:你不能在sizeof(int)> sizeof(char)的平台上用memset替换上面的代码.试试吧.
你如何使用memset将int数组初始化为大于255的某个值?memset仅在数组为字节大小时才有效.
对于记录,这基本上只是一个更慢,更冗长的`memset(myArray,VALUE,ARRAY_SIZE)版本;

7> plinth..:

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

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

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



8> humble_guru..:

这是另一种方式:

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-扩展

指定的内容

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

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



9> warren..:

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

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



10> High Perform..:

一个略微诙谐的答案; 写下声明

array = initial_value

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



11> ddimitrov..:

如果数组恰好是int或任何具有int大小的东西,或者您的mem-pattern的大小适合于int的精确时间(即全零或0xA5A5A5A5),则最好的方法是使用memset()。

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

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有