常用

我们使用memset的时候一般都是将整个数组每一byte进行刷新,如下,但是memset到底是怎样的一回事呢?sizeof为什么看起来像是memset的标配呢?

int a[N];
memset(a,0,sizeof(a));

此外还有一些技巧性应用,下面就是一些原理的介绍。知道下面的原理,就可以用memset做一些标志性的应用

int a[] = {1,2,3,4,5};
    memset(a,-1,sizeof(a));
    for(int i = 0 ; i < sizeof(a)/sizeof(int); i++){
        cout<<a[i]<<endl;
    }
-1
-1
-1
-1
-1

函数介绍

memset函数是C++ <string.h>头文件中的一个函数,它将从给定地址开始,逐个字节刷内存,初始化它们为给定的参数。
基本用法:

void * memset ( void * ptr, int value, size_t num );

因为它是逐字节地刷内存,所以参数num经常用sizeof()的方式写。

事例

char str[] = "This is a new world";
memset (str,'#',6);
puts (str);

输出为:

######s a new world

这里memset的第三个参数是6,也就是从首位&str[0]开始,到&str[5],全部替换为#,不过这里恰好是char类型在该系统上占内存1个字节,这里相当于将char类型用int类型强制转换了。
这时候就会有人想,如果是value=1,是怎样的情况呢

int a[5] = {1,2,3,5,6};
memset(a,1,sizeof(a));
cout<<a[0]<<endl;
//a[0]的值为
16843009

那么,看看啊a[0]内存到底是怎样存储的呢?

//使用unsigned,令高位的第一位不是符号位
unsigned int a = 16843009;
//从高位第一位开始,依次右移到最后一位,&1,表示当前bit是1还是0
for(int i = 31; i >= 0; i--) cout<< (a >> i & 1);

输出结果如下图
在这里插入图片描述可以看到按byte存储了1,也就是类似0x01010101的四字节16进制表示,隐隐约约可以推测是讲value的低位字节截取,覆盖到对应的位置,那么不是0-255区间的数(一个字节无法表示)会如何?

 int a[5] = {1,2,3,5,6};
 memset(a,-2,sizeof(a));
 cout<<a[0]<<endl;
//a[0]的值为
-16843010

同样的验证方式

unsigned int a =-16843010;
for(int i = 31; i >= 0 ;i--) cout<< (a >> i & 1);
//结果为
11111110111111101111111011111110

看一看-2的补码的最低位字节表示

2的源码:00000010
然后-2的计算机表示
   反码:11111101
   补码:11111110

11111110正式上述11111110111111101111111011111110的每个byte所表示的内容。
证明将value的低位字节截取,覆盖到对应的位置的猜测是正确的。
这样回过头看开头的memset(a,-1,sizeof(a))的输出结果是不是就可以理解了呢?

memset与sizeof的相爱相杀

首先确定,sizeof(A)返回的是A占用的栈空间字节数,先看一个事例

    int *a = new int[5];
    cout<<sizeof(a)<<endl;
    //8 指针所用字节数是与系统的寻址能力有关
    //编译器原因64位则为8bytes
    char *a = new char[5];
    cout<<sizeof(a)<<endl;
    //8 所以这里就可以理解了吧
    int b[] = {1,2,3,4,5};
    cout<<sizeof(b)<<endl;
    //20  4*5 = 20
    int *c = b;
    cout<<sizeof(c)<<endl;
    //8
    delete [] a;

这里还有一些关于栈与堆的高维数组存储地址是否连续的问题,不想写了,还是看别人的博客比较轻松

https://www.cnblogs.com/felixfang/p/4220758.html

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐