嵌入式C語言編程時(shí),變量、數(shù)組、指針初始化的多種操作
關(guān)注、星標(biāo)公眾號,直達(dá)精彩內(nèi)容
來源:網(wǎng)絡(luò)素材,侵刪
在敲代碼的時(shí)候,我們會給變量一個(gè)初始值,以防止因?yàn)?strong style="max-width: 100%;outline: 0px;overflow-wrap: break-word !important;box-sizing: border-box !important;">編譯器的原因造成變量初始值的不確定性。
對于數(shù)值類型的變量往往初始化為0,但對于其他類型的變量,如字符型、指針型等變量等該如何初始化呢?
數(shù)值類變量初始化
0。1int????inum??=?0;
2float??fnum?=?0.00f;
3double?dnum?=?0.00;字符型變量初始化
'\0'。1char?ch?=?'\0';?字符串初始化
'\0'。方法一:使用空的字符串 ""。
char str[10] = "";
方法二:使用 memset。
char str[10];
memset(str, 0, sizeof(str));
方法三:寫一個(gè)循環(huán)。
char str[10];
for(int i = 0; i < 10; i++)
{
str[i] = '\0';
}
memset進(jìn)行初始化。很多人對 memset這個(gè)函數(shù)一知半解,只知道它可以初始化很多數(shù)據(jù)類型的變量,卻不知道其原理是什么樣的,這里做一下簡要的說明:memset是按照字節(jié)進(jìn)行填充的。
先看下面的一段代碼:
int num;
memset(&num, 0, sizeof(int));
printf("step1=%d\n", num);
memset(&num, 1, sizeof(int));
printf("step2=%d\n", num);
在討論之前,我們先看一下運(yùn)行結(jié)果
chenyc@DESKTOP-IU8FEL6:~/src$ gcc -o memset memset.c -g
chenyc@DESKTOP-IU8FEL6:~/src$ ./memset
step1 = 0
step2 = 16843009
chenyc@DESKTOP-IU8FEL6:~/src$
看到這個(gè)運(yùn)行結(jié)果,是不是和你想象中的不一樣呢? step1 = 0?相信大家都好理解,可?step2 = 16843009?很多人就不能理解了。按照一般的慣性思維,不是應(yīng)該?= 1?才對么?
這就是我要說的,memset是按照字節(jié)進(jìn)行填充的。
我們知道,int?型是4個(gè)字節(jié)(每個(gè)字節(jié)有8位),按二進(jìn)制表示出來就應(yīng)該是:
00000000 00000000 00000000 00000000
按照按字節(jié)填充的原則,step1 的結(jié)果就是將4個(gè)字節(jié)全部填充0,所以得到的結(jié)果仍然是0:
00000000 00000000 00000000 00000000
而 step2 則是將每個(gè)字節(jié)都填充為1?(注意是每個(gè)字節(jié),而不是每個(gè)byte位)?,所以相對應(yīng)的結(jié)果就應(yīng)該是:
00000001 00000001 00000001 00000001
大家可以自己將上面那個(gè)二進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制看看,看看是不是 16843009。
所以嚴(yán)格來說,memset函數(shù)本身并不具有初始化的功能,而是一個(gè)單純的按字節(jié)填充函數(shù),只是人們在使用的過程中,擴(kuò)展出了初始化的作用。
字符串在內(nèi)存里是連續(xù)的, 字符串遇 '\0'結(jié)束。
所以我們在初始化的時(shí)候,總是愿意給字符串本身長度加1的長度的內(nèi)存進(jìn)行初始化。
char year[4+1];
memset(year, 0, sizeof(year));
strcpy(year,"2018");
指針初始化
NULL。int *pnum = NULL;
int num = 0;
pnum = #
NULL后,沒有給該指針重新分配內(nèi)存,則會出現(xiàn)難以預(yù)料的錯(cuò)誤(最最常見的就是操作空指針引起的段錯(cuò)誤)。malloc、calloc等函數(shù)申請過動態(tài)內(nèi)存,在使用完后需要及時(shí)釋放,一般釋放掉動態(tài)內(nèi)存后要及時(shí)將指針置空,這也是很多人容易忽略的。char *p = NULL;
p=(char *)malloc(100);
if(NULL == p)
{
printf("Memory Allocated at: %x\n",p);
}
else
{
printf("Not Enough Memory!\n");
}
free(p);
p = NULL; //這一行給指針置空必不可少,否則很可能后面操作了這個(gè)野指針而不自知,從而導(dǎo)致出現(xiàn)嚴(yán)重的問題
memset來對該指針進(jìn)行初始化:void fun(char *pstr)
{
memset(pstr, 0, sizeof(pstr));
...
}
memset來進(jìn)行初始化,指針首先保存的是一個(gè)4字節(jié)的地址,所以sizeof(pstr)永遠(yuǎn)只能?= 4,這樣的初始化就毫無意義。結(jié)構(gòu)體初始化
memset的方式。typedef struct student
{
int id;
char name[20];
char sex;
}STU;
STU stu1;
memset((char *)&stu1, 0, sizeof(stu1));
memset的第三個(gè)參數(shù),一般來說,傳入數(shù)據(jù)類型和變量名效果是一樣的,上例中,下面寫法是等價(jià)的效果:memset((char *)&stu1, 0, sizeof(STU));
STU stus[10];
memset((char *)&stus, 0, sizeof(stus)); //正確,數(shù)組本身在內(nèi)存里就是連續(xù)的,sizeof取出的就是數(shù)組的字節(jié)長度
memset((char *)&stus, 0, sizeof(STU)); //錯(cuò)誤,只會初始化第一個(gè)STU結(jié)構(gòu)體,后面還有9個(gè)STU元素并未初始化
memset((char *)&stus, 0, sizeof(STU)*10); //正確,效果與第一個(gè)是一樣的
memset的第二個(gè)參數(shù)寫成以下形式:memset((char *)&stu1, 0x00, sizeof(stu1));
memset是按字節(jié)進(jìn)行填充的,就知道這樣寫也是正確的,完全沒有問題。???????????????? ?END ????????????????? 關(guān)注我的微信公眾號,回復(fù)“加群”按規(guī)則加入技術(shù)交流群。
歡迎關(guān)注我的視頻號:
點(diǎn)擊“閱讀原文”查看更多分享,歡迎點(diǎn)分享、收藏、點(diǎn)贊、在看。
評論
圖片
表情
