为什么是以下程序的输出84215045
?
int grid[110];
int main()
{
memset(grid, 5, 100 * sizeof(int));
printf("%d", grid[0]);
return 0;
}
memset
将目标缓冲区的每个字节设置为指定值。在您的系统上,anint
是四个字节,在调用memset
. 因此,grid[0]
具有十进制值0x05050505
(十六进制)84215045
。
一些平台提供了替代 API 来memset
将更广泛的模式写入目标缓冲区;例如,在 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
84215045
十六进制是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。
你实际上并没有说你想让你的程序做什么。
假设您要将前 100 个元素中的每一个都设置grid
为 5(并忽略100
与110
差异),只需执行以下操作:
for (int i = 0; i < 100; i ++) {
grid[i] = 5;
}
我了解您担心速度,但您的担心可能是错误的。一方面,memset()
可能会被优化,因此比简单的循环更快。另一方面,优化可能包括一次写入多个字节,这就是这个循环所做的。另一方面,memset()
无论如何都是一个循环;显式编写循环而不是将其埋在函数调用中并不会改变这一点。另一方面,即使循环很慢,也可能无关紧要。专注于编写清晰的代码,如果实际测量表明存在严重的性能问题,则考虑对其进行优化。
你写问题所花费的时间比你的计算机设置所花费的时间要多几个数量级grid
。
最后,在我手忙脚乱(为时已晚!)之前,memset()
如果它没有按照您的意愿行事,那么速度有多快并不重要。(完全不设置grid
甚至更快!)
如果你man memset
在 shell 上输入,它会告诉你
void * memset(void *b, int c, size_t len)
一个简单的英语解释是,它用每个字节填充一个b
长度的字节字符串len
value c
。
对于你的情况,
memset(grid, 5, 100 * sizeof(int));
由于sizeof(int)==4
,因此上面的代码片段看起来像:
for (int i=0; i<100; i++)
grid[i]=0x05050505;
或者
char *grid2 = (char*)grid;
for (int i=0; i<100*sizeof(int); i++)
grid2[i]=0x05;
它将打印出84215045
但在大多数 C 代码中,我们希望将一块内存块初始化为零。
char
输入 -->\0
或NUL
int
输入-->0
float
输入-->0.0f
double
输入-->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 委员会并没有强加这样的定义,它是特定于编译器的。
由于 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。
此代码已经过测试。这是一种将“整数”数组设置为 0 到 255 之间的值的方法。
MinColCost=new unsigned char[(Len+1) * sizeof(int)];
memset(MinColCost,0x5,(Len+1)*sizeof(int));
memset(MinColCost,0xff,(Len+1)*sizeof(int));