为什么以下程序的输出为84215045
?
int grid[110];
int main()
{
memset(grid, 5, 100 * sizeof(int));
printf("%d", grid[0]);
return 0;
}
答案 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
处理。
84215045
是0x05050505
;因为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(并忽略100
与110
差异),请执行以下操作:
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; \0
或NUL
int
类型 - &gt; 0
float
类型 - &gt; 0.0f
double
类型 - &gt; 0.0
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));