当前位置: 代码迷 >> 综合 >> C/C++选择部分数组元素为指定的值:memset()和fill()
  详细解决方案

C/C++选择部分数组元素为指定的值:memset()和fill()

热度:99   发布时间:2024-01-12 15:45:43.0

文章目录

  • 一、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函数是以字节为单位进行赋值的】

  1. 取值过程:取表示值的_Val参数的一个低位字节Byte
    我们都知道int类型是4个字节,一个字节Byte是8bit。比如例子中传入0,其实是0x0000 000000000000 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?)
    同理,-10xffff ffff11111111 11111111 11111111 11111111),而511是0x0000 01ff00000000 00000000 00000001 11111111)的后八位都为0xff11111111),所以int a[5]赋值memset(a, -1, sizeof(int)*5)memset(a, 511, sizeof(int)*5)所赋值的结果是一样的都为-1
  2. 赋值过程
    _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;}
}

【解析:firstlast其实也是获得地址的位置,但是有限制】
它是用*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-百度百科

  相关解决方案