为什么memset()错误地初始化int?

时间:2011-08-17 22:57:19

标签: c++ c memset

为什么以下程序的输出为84215045

int grid[110];
int main()
{
    memset(grid, 5, 100 * sizeof(int));
    printf("%d", grid[0]);
    return 0;
}

9 个答案:

答案 0 :(得分:43)

memset将目标缓冲区的每个字节设置为指定值。在您的系统上,int是四个字节,在调用memset后每个字节为5。因此,grid[0]的值为0x05050505(十六进制),十进制为84215045

某些平台为memset提供了替代API,可以将更宽的模式写入目标缓冲区;例如,在OS X或iOS上,您可以使用:

int pattern = 5;
memset_pattern4(grid, &pattern, sizeof grid);

获取您似乎期望的行为。您定位的平台是什么?

在C ++中,您应该只使用std::fill_n

std::fill_n(grid, 100, 5);

答案 1 :(得分:12)

memset(grid, 5, 100 * sizeof(int));

您要设置400字节(从(char*)grid开始,到(char*)grid + (100 * sizeof(int))结束)到值5(这里需要强制转换,因为memset处理 bytes ,而指针算术在objects处理。

十六进制中的

842150450x05050505;因为int(在您的平台/编译器/等)上由四个字节表示,当您打印它时,您将得到“四个五”。

答案 2 :(得分:8)

memset是关于设置字节,而不是值。在C ++中设置数组值的众多方法之一是std::fill_n

std::fill_n(grid, 100, 5);

答案 3 :(得分:6)

请勿使用memset。

将内存的每个字节[]设置为值5.每个int长度为4个字节[5][5][5][5],编译器正确解释为5 * 256 * 256 * 256 + 5 * 256 * 256 + 5 * 256 + 5 = 84215045.相反,使用for循环,也不需要sizeof()。一般来说,sizeof()意味着你正在做一些艰难的事情。

for(int i=0; i<110; ++i)
    grid[i] = 5;

答案 4 :(得分:3)

好吧,memset使用所选值写入字节。因此int看起来像这样:

00000101 00000101 00000101 00000101

然后将其解释为84215045。

答案 5 :(得分:2)

你实际上没有说过你希望你的程序做什么。

假设您要将grid的前100个元素中的每一个设置为5(并忽略100110差异),请执行以下操作:

for (int i = 0; i < 100; i ++) {
    grid[i] = 5;
}

我知道你关注速度,但你担心的可能是错位的。一方面,memset()可能会被优化,因此比简单循环更快。另一方面,优化可能包括一次写入多个字节,这就是这个循环的作用。另一方面,memset()无论如何都是一个循环;明确地编写循环而不是将其隐藏在函数调用中并不会改变它。另一方面,即使循环缓慢,也不太重要;专注于编写清晰的代码,并考虑优化它如果实际测量表明存在重大的性能问题。

你写这个问题的时间要比计算机设置grid花费多出几个数量级。

最后,在我用完手之前(太迟了!),如果它没有做你想要的那么快memset()就没关系。 (根本不设置grid甚至更快!)

答案 6 :(得分:1)

如果您在shell上输入man memset,它会告诉您

  

void * memset(void *b, int c, size_t len)

对此的简单英语解释是,它填充长度为b的字节字符串len,每个字节的值为c

对于您的情况,

memset(grid, 5, 100 * sizeof(int));

sizeof(int)==4开始,上面的代码就像:

for (int i=0; i<100; i++)
    grid[i]=0x05050505;

OR

char *grid2 = (char*)grid;
for (int i=0; i<100*sizeof(int); i++)
    grid2[i]=0x05;

会打印出 84215045

但是在大​​多数C代码中,我们想要将一块内存块初始化为零值。

  • char类型 - &gt; \0NUL
  • int类型 - &gt; 0
  • float类型 - &gt; 0.0f
  • double类型 - &gt; 0.0
  • 指针类型 - &gt; nullptr

gcc clang 等。现代编译器可以自动为您完成此任务。

// variadic length array (VLA) introduced in C99
int len = 20;
char carr[len];
int iarr[len];
float farr[len];
double darr[len];
memset(carr, 0, sizeof(char)*len);
memset(iarr, 0, sizeof(int)*len);
memset(farr, 0, sizeof(float)*len);
memset(darr, 0, sizeof(double)*len);
for (int i=0; i<len; i++)
{
    printf("%2d: %c\n", i, carr[i]);
    printf("%2d: %i\n", i, iarr[i]);
    printf("%2d: %f\n", i, farr[i]);
    printf("%2d: %lf\n", i, darr[i]);
}

但请注意,C ISO委员会并没有强加这样的定义,而是针对编译器。

答案 7 :(得分:0)

由于memset写入字节,我通常用它来将int数组设置为零,如:

int a[100];
memset(a,0,sizeof(a));

或者您可以使用它来设置char数组,因为char只是一个字节:

char a[100];
memset(a,'*',sizeof(a));

更重要的是,一个int数组也可以通过memset设置为-1:

memset(a,-1,sizeof(a));

这是因为-1在int中是0xffffffff,在char(一个字节)中是0xff。

答案 8 :(得分:0)

此代码已经过测试。这是一种将“整数”数组设置为0到255之间的值的方法。

MinColCost=new unsigned char[(Len+1) * sizeof(int)];

memset(MinColCost,0x5,(Len+1)*sizeof(int));

memset(MinColCost,0xff,(Len+1)*sizeof(int));