为什么memset()不正确地初始化int?
为什么下面的程序84215045
的输出?
int grid[110]; int main() { memset(grid, 5, 100 * sizeof(int)); printf("%d", grid[0]); return 0; }
memset
将目标缓冲区的每个字节设置为指定的值。 在你的系统上,一个int
是四个字节,在调用memset
之后每个字节都是五个字节。 因此, grid[0]
的值为0x05050505
(hex),十进制为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);
memset(grid, 5, 100 * sizeof(int));
您将设置400个字节,以(char*)grid
开始,以(char*)grid + (100 * sizeof(int))
,值为5
(因为memset
以字节为单位进行处理 ,交易objects
。
在hex中的0x05050505
是0x05050505
; 因为int
(在你的平台/编译器/等)由四个字节表示,所以当你打印它时,你会得到“四五”。
memset
是关于设置字节,而不是值。 在C ++中设置数组值的方法之一是std::fill_n
:
std::fill_n(grid, 100, 5);
不要使用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;
那么, memset
用选定的值写入字节。 因此int将看起来像这样:
00000101 00000101 00000101 00000101
然后解释为84215045。
你实际上并没有说你想要你的程序做什么。
假设你想将grid
的前100个元素设置为5(并忽略100
与110
差异),只需执行以下操作:
for (int i = 0; i < 100; i ++) { grid[i] = 5; }
我知道你对速度很关心,但你的担心可能是错误的。 一方面, memset()
很可能被优化,因此比简单的循环更快。 另一方面,优化可能包括一次写入多个字节,这就是这个循环所做的。 另一方面, memset()
无论如何都是一个循环; 明确写入循环而不是将其隐藏在函数调用中不会改变这一点。 另一方面,即使循环很慢,也不太可能; 集中精力编写清晰的代码,并考虑优化它, 如果实际测量结果表明存在显着的性能问题。
你花了很多数量级的时间来写这个问题,而不是你的计算机花费的时间来设置grid
。
最后,在我用完手之前(太迟了!), memset()
是不是有多快,如果它不做你想要的。 (根本不设置grid
更快!)
由于memset写入字节,我通常使用它来设置一个int数组为零:
int a[100]; memset(a,0,sizeof(a));
或者你可以使用它来设置一个字符数组,因为一个字符恰好是一个字节:
char a[100]; memset(a,'*',sizeof(a));
更重要的是,int数组也可以通过memset设置为-1:
memset(a,-1,sizeof(a));
这是因为在int中-1是0xffffffff,在char(一个字节)中是0xff。
此代码已经过testing。 这是将“整数”数组的值设置为0到255之间的一种方法。
MinColCost=new unsigned char[(Len+1) * sizeof(int)]; memset(MinColCost,0x5,(Len+1)*sizeof(int)); memset(MinColCost,0xff,(Len+1)*sizeof(int));