memset的区别?

时间:2012-06-25 23:20:09

标签: c++ pointers

我确实在msdn和cplusplus.com上阅读了memset的用法,我知道(如果我错了请纠正我):

int p =3;
// p = object value
// &p = memory address where p is stored

那有什么区别:

char szMain[512];
memset( szMain, 0x61, sizeof( szMain ) );
cout << szMain[4];

char szMain[512];
memset( &szMain, 0x61, sizeof( szMain ) );
cout << szMain[4];

(0x61 = a,ASCII表格十六进制)

为什么两者都有相同的行为?如果这不是一个建设性的问题,请原谅我。 我有点像c ++的新手,我似乎无法理解。

3 个答案:

答案 0 :(得分:4)

标准中将所发生的事情描述为数组到指针的转换

  

4.2数组到指针的转换[conv.array]

     

“N T数组”或“未知数组的数组”的左值或右值   “可以将T”转换为“指向T”的类型的右值。结果   是指向数组第一个元素的指针。


上面说过,在第一次调用memset szMain时会转换为指针(更具体地说是指向char的指针),存储数组第一个元素的地址。

在第二次调用中,&szMain将产生类型为char (*)[512]的指针,即。指向与szMain具有相同类型的数组的指针,存储数组本身的地址。

这两个表达式都会产生相同的确切值,因为szMain的开头位于与它的第一个元素(szMain[0])相同的地址,但请注意,不是同一类型。


memset接受void*作为第一个参数,因此可以隐式使用任何指针类型来调用该函数。

答案 1 :(得分:3)

szMain是数组的标识符。在大多数情况下,数组标识符会衰减成为指向数组中第一个元素的指针,换句话说就是&szMain[0]

所以在你的第一个例子中,你传递memset数组第一个元素的地址。在第二个示例中,您将传递数组本身的地址。但是,这些地址完全相同。

答案 2 :(得分:2)

是的,在这种情况下,两者具有相同的行为,但情况并非总是如此。

数组名称的大多数用法都给出了数组第一个元素的地址。对于T数组,指针的类型将为T *

如果明确地取代数组的地址,则获得相同的地址,但是不同的类型(“指向类型为T的N个对象的数组的指针”而不是“指向T的指针”)。

在这种情况下,您传递的地址将转换为void *,因此会立即丢弃类型的差异 - 但如果您在另一个不立即丢弃类型差异的上下文中使用它们,不一定会产生同样的效果。例如,如果您想要取消初始化数组的第一个元素,您可能会执行以下操作:

memset(szMain+1, 'a', sizeof(szMain));

由于类型(在这种情况下)是“指向char的指针”,它将根据需要从数组中的第二个char开始。但是,如果你这样做了:

memset(&szMain+1, 'a', sizeof(szMain));

它不会添加1,而是添加一个数组的大小,因此您将在数组结束后传递地址,而不是第二个元素的地址。

顺便说一句:如果你想要'a',我建议你直接使用它,就像我在上面那样,而不是像在问题中那样用十六进制编码值。至少,它更具可读性。它在理论上也更具可移植性,但很少有人真正关心十六进制值无法正常工作的机器(主要是IBM大型机)。