我在C中有一个大型数组(如果有所不同,则不是C ++)。我想初始化所有具有相同值的成员。
我可以发誓曾经有一种简单的方法可以做到这一点。我可以memset()
在我的情况下使用,但是没有办法直接在C语法中内置吗?
memset()
具体论述:stackoverflow.com/questions/7202411/...我认为它仅适用于0
我在C中有一个大型数组(如果有所不同,则不是C ++)。我想初始化所有具有相同值的成员。
我可以发誓曾经有一种简单的方法可以做到这一点。我可以memset()
在我的情况下使用,但是没有办法直接在C语法中内置吗?
memset()
具体论述:stackoverflow.com/questions/7202411/...我认为它仅适用于0
Answers:
除非该值为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,指针指向空值,等等。)
如果您的编译器是GCC,则可以使用以下语法:
int array[1024] = {[0 ... 1023] = 5};
查看详细说明:http : //gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html
int
s 添加到静态数据中,即256 K-恰好是您观察到的大小增加。
int
s,则int foo1 = 1, foo2 = 1, ..., foo65536 =1;
您将获得相同的大小增加。
bool array[][COLS] = { [0...ROWS-1][0...COLS-1] = true}
尽管我不确定这比完整的格式更具可读性。
为了静态初始化具有相同值的大型数组,而无需进行多次复制粘贴,可以使用宏:
#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) };
宏名称可以协商。
VAL_1X
不是单个整数而是一个列表,也可以使用此方法。像可迁移状态一样,这也是您要定义EEPROM或闪存的初始化值的嵌入式系统的方法。在这两种情况下,您都不能使用memset()
。
如果要确保显式初始化数组的每个成员,只需从声明中省略维度:
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} };
不是。
int myPoints[10][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
我看到了一些使用此语法的代码:
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)
};
即使您碰巧不按顺序写入一些枚举值,也可以使事情保持秩序。
char const *array[] = { ... };
甚至声明char const * const array[] = { ... };
,不是吗?
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(myArray, VALUE, ARRAY_SIZE);
您可以按照上面的详细说明进行整个静态初始化程序,但是当数组大小更改时,它可能是一个真正的麻烦(当数组包含符号时,如果不添加适当的额外初始化程序,则会产生垃圾)。
memset为您提供了执行工作所需的运行时命中率,但没有正确完成代码大小命中率不受阵列大小更改的影响。当数组大于几十个元素时,几乎在所有情况下都可以使用此解决方案。
如果对数组进行静态声明确实很重要,那么我将编写一个程序来为我编写该程序,并将其作为构建过程的一部分。
memset
初始化数组方面添加一些示例?
这是另一种方式:
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},
};
看到:
指定的inits
然后问一个问题:什么时候可以使用C扩展?
上面的代码示例在嵌入式系统中,永远不会看到其他编译器发出的光。
有一种快速的方法可以初始化具有给定值的任何类型的数组。它在大型阵列上效果很好。算法如下:
对于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;
}
memfill()
代码大约需要1200 µs。但是,在后续迭代中,循环大约需要900-1000 µs,而memfill()
代码需要1000-1300 µs。第一次迭代可能会受到填充缓存时间的影响。撤消测试,memfill()
第一次速度很慢。
没有人提到索引顺序来访问初始化数组的元素。我的示例代码将给出一个说明性示例。
#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
<iostream>
无效,C
因为std::cout
,std::cin
等是的一部分,std::namespace
并且C
不支持namespaces
。尝试改用<stdio.h>
for printf(...)
。
#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 ......直到整个数组的大小
我知道用户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()
功能以支持这些类型。
您可以使用此处找到的在线编译器尝试使用此代码。
我知道原始问题明确提到了C而不是C ++,但是如果您(像我一样)来到这里寻找C ++数组的解决方案,这是一个巧妙的技巧:
如果您的编译器支持fold expressions,则可以使用template 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
您可以查看工作中的代码(在Wandbox中)
我认为这个问题没有任何要求,因此解决方案必须是通用的:初始化一个未指定的可能是多维数组,该数组是使用未指定的可能具有初始成员值的结构元素构建的:
#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
sizeof(void)
有效。
memcpy()
与目标空间重叠,所以调用了未定义的行为。使用的天真的实现memcpy()
,它可能会起作用,但是并不需要系统使其起作用。
回顾过去(我并不是说这是个好主意),我们将设置第一个元素,然后:
memcpy (&element [1], &element [0], sizeof (element)-sizeof (element [0]);
甚至不确定它是否会继续工作(这取决于memcpy的实现),但它可以通过将初始元素重复复制到下一个元素来工作-甚至适用于结构数组。
memcpy
但在重叠的情况下应指定自下而上或自上而下的复制顺序,但事实并非如此。
如果您的意思是并行的,那么我认为将逗号运算符与表达式结合使用可以做到这一点:
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)
等等。
enum { HYDROGEN = 1, HELIUM = 2, CARBON = 6, NEON = 10, … };
和struct element { char name[15]; char symbol[3]; } elements[] = { [NEON] = { "Neon", "Ne" }, [HELIUM] = { "Helium", "He" }, [HYDROGEN] = { "Hydrogen", "H" }, [CARBON] = { "Carbon", "C" }, … };
。如果删除省略号…
,这些片段会在C99或C11下编译。