Interesting memset [zz]

memset()
memset的特点是:将给定地址后连续的内存(包括给定地址),逐个byte初始化为参数中指明的值。

  1. 因为是逐byte初始化,所以memset一般只用来清空(赋值为0)
    如果不赋值为0,结果是什么呢?假设对于int A[],如果使用memset(A, 1, sizeof(A)),那么数组A的每一个值会被初始化为0x01010101。正因为如此,一般只会出现 memset(A, 0, sizeof(A))

  2. 对于堆区分配的数组
    int *A = new int[N], memset(A, 0, sizeof(A[0])*N) 也可以达到效果,但要注意,这里第三个参数不能使用sizeof(A),而要指明byte数。要想知道原因,需要知道sizeof 运算符的作用。它返回的是“占用的栈空间字节数**”。

如果数组用int A[N]的形式申明,那么sizeof(A)返回的是整个A数组的占用byte数。
如果用int *A = new int[N],sizeof(A)返回的依旧是一个int *所占用的byte数,也就是说,32位编译器会返回 4,64位编译器会返回8 。需要注意的是,对于两种编译器,sizeof作用在int *才会有区别,而sizeof(int) 在两种编译器上都返回4。

  1. 二维数组的初始化
    知道了上面的原理,我们来看看二维数组的初始化。
    int A[2][3] 对于这样的定义方式,我们依然可以通过memset(A, 0, sizeof(A))来完成对整个二维数组的初始化,因为这种方式申明的二维数组本质上还是一维排列。

如果是int **A,然后动态申明一个2*3的二维数组呢?我们可以像上面一样,通过 memset(A, 0, sizeof(A[0][0])*2*3)来完成二维数组的初始化吗?答案自然是不行。

动态分配的一维数组之所以依然能用memset(虽然第三参数要指明byte数)来完成赋值,因为在堆区,一维数组的成员依然是连续排列。

动态分配的二维数组中的int成员在堆区还是连续排列的吗?当然不是,既然不是,memset就不能得到想要的结果了。

那实际结果是啥?memset会清空存放二级指针的连续内存,附带清除些别的内存区域。之后只要访问诸如A[0][1]之类的都会引发内存错误,因为二维数组的结构已经被破坏。

from here

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • SwiftDay011.MySwiftimport UIKitprintln("Hello Swift!")var...
    smile丽语阅读 9,243评论 0 6
  • 这个是初始版本,还会进行改正和补充,请大家认真熟悉这些基础知识!如有错误,请在评论区留言@作者 总体上必须清楚的:...
    亦一银河阅读 7,249评论 3 40
  • 少女的花样年华 是繁华里的繁花 小小嫩嫩的枝芽 开出了繁繁的花 花开时 人们来往繁杂 花败后 可还有人看她 美丽的...
    步千谨阅读 2,994评论 0 1
  • 在爱情中,多多少少是需要一点对等关系的。如果一方倾尽所有,而另一方却丝毫不让,这样的感情在时日渐深之后,总会出现因...
    何德恺阅读 4,039评论 0 4
  • 两枝紫罗兰,同时发新芽,同时长新叶,生长速度是一样的,生长的方向也是一样的向上、朝阳,长出来的整体形态模样气质也是...
    花与熙阅读 884评论 0 0