C memset 踩坑
一、前言
memset 作為對(duì)內(nèi)存初始化的函數(shù),還是有不少坑和誤區(qū)的,今天就來(lái)對(duì)這個(gè)函數(shù)作一個(gè)總結(jié)。
二、函數(shù)作用
最簡(jiǎn)單的調(diào)用就是將一個(gè)數(shù)組清零,代碼如下:
這里 sizeof(a) = maxn * 4 = 4096;
表示的是將?數(shù)組首地址 a 開(kāi)始往后的 4096 個(gè)字節(jié),都設(shè)置為 0;
三、效率對(duì)比
直接調(diào)用 memset 接口清零 和 調(diào)用循環(huán)進(jìn)行清零,進(jìn)行一個(gè)測(cè)試后如下:
對(duì)長(zhǎng)度為 10000000 的數(shù)組,執(zhí)行100次調(diào)用;
| 模式 | memset | for |
debug | 375ms | 2156ms |
release | 343ms | 329ms |
因?yàn)?release 版本會(huì)做各種優(yōu)化,編譯器發(fā)現(xiàn)重復(fù)執(zhí)行無(wú)效邏輯就會(huì)跳過(guò),所以不太好造數(shù)據(jù)測(cè)試,研究時(shí)間效率的時(shí)候還是參考 debug 版本(當(dāng)然,軟件發(fā)布的時(shí)候肯定用的是 release 版本)。
memset 無(wú)論從時(shí)間效率,還是代碼整潔來(lái)看都是由于 for 循環(huán)的,當(dāng)然也帶來(lái)了一些容易引起誤解的地方。
四、誤區(qū)總結(jié)
1、按字節(jié)設(shè)置
memset 實(shí)現(xiàn)原理是根據(jù)字節(jié)來(lái)設(shè)置的,比如對(duì)于字節(jié)數(shù)組char a[100],將所有字節(jié)都設(shè)置為5,就可以調(diào)用:
但是,對(duì)于int b[100],也采用這種方法,就會(huì)導(dǎo)致錯(cuò)誤:
得到 b 數(shù)組中元素的值為 84215045;
為什么呢?
我們把這個(gè)數(shù)組轉(zhuǎn)換成二進(jìn)制,得到:
( 00000101 00000101 00000101 00000101 ) 2 (00000101 \ 0000 0101 \ 0000 0101 \ 0000 0101)_2 (00000101 ?00000101 ?00000101 ?00000101)2因?yàn)?i n t int int 占據(jù)了 4 4 4 個(gè)字節(jié),把每個(gè)字節(jié)都設(shè)置成了5,所以最后轉(zhuǎn)成十進(jìn)制就變成了 84215045;
同理,當(dāng)類(lèi)型是 short(二字節(jié)整數(shù)),或者 long long(八字節(jié)整數(shù))都會(huì)有類(lèi)似問(wèn)題,總結(jié)表格如下:
| memset值 | char | short | int | long long |
0 | 0 | 0 | 0 | 0 |
-1 | -1 | -1 | -1 | -1 |
5 | 5 | 1285 | 84215045 | 361700864190383365 |
表格中,只有0 和 -1是正常的,因?yàn)?0 的二進(jìn)制表示中,所有位都為0;-1 的二進(jìn)制表示中,所有位都為 1;
特別的,當(dāng)需要設(shè)置的數(shù),對(duì)應(yīng)類(lèi)型的每個(gè)字節(jié)都是同一個(gè)數(shù)的時(shí)候,也可以采用 memset,比如:int 類(lèi)型的 252645135(十六進(jìn)制表示為:0x0f0f0f0f);
2、設(shè)置的值只有最低字節(jié)有效
memset(a,?0x05ffffff,?sizeof(a)); memset(a,?0xffffff05,?sizeof(a)); memset(a,?0xffffff08,?sizeof(a)); memset(a,?0x12345678,?sizeof(a));設(shè)置值的時(shí)候,只會(huì)采用最低的字節(jié)作為賦值用,通俗的講,就是以上四句話調(diào)用,等價(jià)于:
3、堆內(nèi)存不可直接 sizeof 取首地址
在堆上申請(qǐng)了一個(gè)數(shù)組空間,并且想要給它初始化,調(diào)用如下:
這里進(jìn)入了另一個(gè)誤區(qū),因?yàn)?p p p 在這里雖然是數(shù)組首地址,但是它扮演的角色更多的,其實(shí)是個(gè)指針,所以在進(jìn)行 sizeof 運(yùn)算符操作的時(shí)候,取得的值并不是 4096,而是指針的大小;
32位機(jī)子上,指針大小為4,;64位機(jī)子上,指針大小為 8;
正確做法是:
4、傳參數(shù)組不可直接 sizeof 取首地址
對(duì)傳參為數(shù)組的數(shù)據(jù)進(jìn)行 memset,調(diào)用如下:
這里調(diào)用同樣是錯(cuò)誤的,因?yàn)楫?dāng)數(shù)組作為傳參的時(shí)候,這里的 a 已經(jīng)退化為指針,所以同樣不能用 sizeof 數(shù)組首地址來(lái)取大小;
正確做法是:
當(dāng)然,當(dāng)傳參是結(jié)構(gòu)體指針的時(shí)候也是如此;
- EOF -
來(lái)源:
https://blog.csdn.net/WhereIsHeroFrom/article/details/111660632
總結(jié)
以上是生活随笔為你收集整理的C memset 踩坑的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 低估值板块有哪些?
- 下一篇: 散户可以长期持有一只股票吗?