文章目录
- 一、memset()
-
- 1.头文件
- 2.函数原型
- 3.使用
-
- (1)赋值int数组
- (2)赋值char数组
- (3)结构体
- 二、fill()
-
- 1.头文件
- 2.函数原型
- 3.例子
-
- (1)数组
- 三、总结
-
- 1.都可以挑选位置设置
- 2.sizeof()的陷阱
- Reference
一、memset()
C/C++通用
1.头文件
C:#include<string.h>
C++:#include<cstring>
or #include<string.h>
2.函数原型
【作用】:将已开辟内存空间_Dst
的首_Size
个字节的值设为值_Val
。
void *memset(void *_Dst, int _Val, size_t _Size)
【例子】:
int a[5];
memset(a, 0, sizeof(a));
【解析:memset
函数是以字节为单位进行赋值的】
- 取值过程:取表示值的
_Val
参数的一个低位字节Byte。
我们都知道int
类型是4个字节,一个字节Byte是8bit。比如例子中传入0
,其实是0x0000 0000
(00000000 00000000 00000000 00000000
),十六进制下的一位表示4位bit,即两位十六进制表示一个字节。取得就是 0x0000 00 00 (00000000 00000000 00000000 00000000 ) \text{0x0000 00\boxed{00}(00000000 00000000 00000000 \boxed {00000000})} 0x0000 0000?(00000000 00000000 00000000 00000000?)。
同理,-1
是0xffff ffff
(11111111 11111111 11111111 11111111
),而511是0x0000 01ff
(00000000 00000000 00000001 11111111
)的后八位都为0xff
(11111111
),所以int a[5]
赋值memset(a, -1, sizeof(int)*5)
与memset(a, 511, sizeof(int)*5)
所赋值的结果是一样的都为-1
。 - 赋值过程
将_Val
取的一个低位字节为单位,填充满所要初始化的空间。比如上面的例子中用0
赋值得到数组元素都是0
,就是因为a[0]
就是用赋值了四个0x00
字节,组合到一起刚好又是0
。
【解析:_Dst
就是地址位置】
这东西就是获得一个指向开始位置的地址嘛,那么就是获得数组的首地址的那几种方法嘛。
3.使用
(1)赋值int数组
如果用int
类型赋值的话,要取每个字节都相同的值,因为别的值因为字节拆分组合起来就不是本身了。
比如用0或-1初始化,用0x3f3f3f3f
(表示ACM中的无穷大)。
int a[5];memset(a, 0, sizeof(a));
memset(&a[0], 0, sizeof(a));
memset(a, 0, 5 * sizeof(int));
int a[5][5];memset(a, 0, sizeof(a));
memset(a[0], 0, sizeof(a));
memset(&a[0][0], 0, sizeof(a));
memset(a, 0, 25 * sizeof(int));
(2)赋值char数组
如果用char
类型赋值的话,就是char
本身。
因为char
类型可以表示为ASCII码表示的int
值,比如A
就是65。
一般是赋值'\0'
,'0'
,'1'
之类的(要加单引号)。
char a[5];
memset(a, 'A', sizeof(a));
for (int i = 0; i < 5; i++)
{
cout << a[i] << " ";
}
cout << endl;
// A A A A A
(3)结构体
结构体也是按照字节为单位存储的
/* 一般的结构的清空操作 */
struct Student
{
char name[16];int id;
};
struct Student Tom;
// 因为char数组只要出现'\0'就代表结束了
Tom.name[0] = {
'\0'};
Tom.id = 0;/* 用memset()清空结构体 */
memset(&Tom, 0, sizeof(Tom));
// 注意&
如果是结构体数组:
struct Student students[10];
memset(students, 0, sizeof(students) * 10);
PS:【需要再研究下,结构体对齐问题,比如name[17]时;“如果结构体中有数组的话还是需要对数组单独进行初始化处理的。”啥意思】
二、fill()
C++专用
1.头文件
#include <iostream>
using namespace std;
2.函数原型
作用:将val
赋给范围内的所有元素[first, last]
。
fill 的前两个参数是定义序列的正向迭代器,第三个参数是赋给每个元素的值。
只要在类型表示的范围内,val
随便赋值。
template <class ForwardIterator, class T>void fill (ForwardIterator first, ForwardIterator last, const T& val)
{
while (first != last) {
*first = val;++first;}
}
【解析:first
和last
其实也是获得地址的位置,但是有限制】
它是用*first
来获得值修改的,所以只能套一层,*p
直接就是值,不能**p
才获得值。
3.例子
(1)数组
int a[5];fill(a, a + 5, 0);
fill(&a[0], a + 5, 0);
fill(&a[0], &a[5], 1); // 因为是"不到last"
fill(&a[0], a + sizeof(a) / sizeof(int), 1);
fill(&a[0], a + sizeof(a) / sizeof(a[0]), 1);
int a[5][5];// fill(a, a + 5 * 5, 0); // 报错,'const int' to 'int [5]'
// fill(&a, &a + 5 * 5, 0); // 报错,'const int' to 'int [5][5]'
// fill(&a[0], &a[0] + 5 * 5, 0); // 报错,'const int' to 'int [5]'
fill(a[0], a[0] + 5 * 5, 0);
fill(&a[0][0], &a[5][5], 0);
fill(&a[0][0], &a[0][0] + 5 * 5, 0);
fill(&a[0][0], &a[0][0] + sizeof(a) / sizeof(int), 0);
三、总结
1.都可以挑选位置设置
并不局限于只是全部的元素
int a[5] = {
};memset(&a[1], -1, sizeof(int) * 2);
// memset(&a[1], -1, (&a[3] - &a[1]) * sizeof(a[0]));// fill(&a[1], &a[3], -1);for (int i = 0; i < 5; i++)
{
cout << a[i] << " ";
}
int a[5][5] = {
};memset(&a[1][2], -1, (&a[3][4] - &a[1][2]) * sizeof(a[0][0]));// fill(&a[1][2], &a[3][4], 0);for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++){
cout << a[i][j] << " ";}cout << endl;
}
cout << endl;
2.sizeof()的陷阱
就是获取所占空间大小的字节数(= 单个元素类型的字节数×数组元素个数),但注意数组传参的陷阱。
(win64下)数组传参进来是一个指针,而指针的类型是8个字节。而不是应该的5x4=20
void fun(int a[5])
{
cout << sizeof(a) << endl;// 8
}
Reference
memset-百度百科