我在 C 中有一个大型数组(如果这有区别的话,不是 C++)。我希望将所有成员初始化为相同的值。
我记得曾经知道一种简单的方法来做到这一点。虽然我可以在我的情况下使用 memset()
,但是否有一种内置于 C 语法中的方法来实现这一点呢?
我在 C 中有一个大型数组(如果这有区别的话,不是 C++)。我希望将所有成员初始化为相同的值。
我记得曾经知道一种简单的方法来做到这一点。虽然我可以在我的情况下使用 memset()
,但是否有一种内置于 C 语法中的方法来实现这一点呢?
对于初始化'正常'数据类型(如int数组),您可以使用方括号表示法,但如果数组中仍有空间,则会将最后一个值之后的所有值都清零:
// put values 1-8, then two zeroes
int list[10] = {1,2,3,4,5,6,7,8};
1 000 000
个元素的int
数组,与常规循环初始化相比,它的速度快4倍(i5,2核,2.3 GHz,4GiB内存,64位):
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()
的首次运行较慢。 - Jonathan Leffler示例: int array[10]; memset(array,-1, 10 *sizeof(int));
int array[1024] = {[0 ... 1023] = 5};
...
之间没有空格。没有人提到访问初始化数组元素的索引顺序。我的示例代码将给出一个说明性的例子。
#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语言不支持命名空间。建议使用<stdio.h>
头文件中的printf(...)
函数代替。 - Francis Cugler不废话,简短回答是:如果你在编译时打开了优化选项,那么你不可能做得比这更好:
int i,value=5,array[1000];
for(i=0;i<1000;i++) array[i]=value;
额外的好处是:代码实际上是可读的 :)
我知道用户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];
在声明时不会直接初始化,但下一个代码块或函数调用会将数组的每个元素初始化为您想要的相同值。另一个注意事项是,您必须为每个您支持的类型
编写一个初始化函数
,并且还必须修改printArray()
函数以支持这些类型。
对于延迟初始化(即类成员构造函数初始化),考虑以下方法:
int a[4];
unsigned int size = sizeof(a) / sizeof(a[0]);
for (unsigned int i = 0; i < size; i++)
a[i] = 0;
要用零初始化 -
char arr[1000] = { 0 };
char arr[1000];
for(int i=0; i<arr.size(); i++){
arr[i] = 'A';
}
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下编译通过。 - Jonathan Lefflermemset()
特定讨论:https://dev59.com/qmw05IYBdhLWcg3wfx80 我认为它只适用于0。 - Ciro Santilli OurBigBook.commemset()
只适用于值为0
、UINT_MAX
和元素大小为char
的数组。 - user16217248