C的陷阱與缺陷 P1-P42 PartI- 學習小結

版主開設這一個坑的目的也是爲了加深自身對c的應用與理解,順便見一見沒用過的庫函數。

1.= is not ==

Most languages originated from Algol(i.e.Pascal and Ada) use token ' := ' to embody  assignment and token '==' to embody if those two part aside the "==" are equal or not.

Let‘s see those codes below:

while(c=''||c=='\t'||c=='\n')
         c=getc(f);

This .c file may run for long cause the first line assigns c to be ' ' (space) which refers to 32 in ASCII standard.

Operator Precedence:

    同一優先級的運算符,運算次序由結合方向所決定。
    簡單記就是:! > 算術運算符 > 關係運算符 > && > || > 賦值運算符

2.& and | is not && and || meanwhile '' is not ""

The first two are bit operator,while the last two are logical opearator.

現在基本上所有編輯器都能檢測到’‘與“”的不同,van題不大。

3.詞法的“貪婪” 

從左到右依次讀入token,如果一個字符可能組成一個符號,那麼在讀入一個符號,看他們倆能不能組成一個符號,只要中間不嵌入無意義符號(space,\t,\n)就繼續下去。比如==是一個符號,而= =是兩個符號

再如,a---b is the same as a-- -b。

又如,y=a/*p,並不是a除以p指向的地址內容的值而是直接開始註釋了。

And we can see what do "a+++b" and "a+++++b "mean。

1.再談優先級:

假設有兩個二進制信號一個叫flag一個叫FLAG,你需要判斷他們是否是同一個信號,對他們合取&,當然你可以這麼些if(flag&FLAG)意思是顯然的;然而如果你需要顯式表達的話,你可能會寫出if(flag&FLAG != 0)然而!=的優先級卻高於&,所以這串代碼還是有問題的。

2.switch的break or no break

3.if-else的就近原則,加括號的重要性

舉例:

if(x==0)
      if(y==0) error();
else
{
z=x+y;
f(&z);
}

4.我們再來複習一下數組與指針的相關內容:

int calendar[12][31];

int *p;

int i;

而calendar[4]是calendar數組的第五個元素,比如sizeof(calendar[4])=31*sizeof(int);

p=calendar[4];這個語句讓p指向數組calendar[4]中下標爲0的元素;同理,calendar[0]這個語句就是指向calendar[0]數組中下標爲0的元素。

i=calendar[4][7]這個意思就是把calendar的第五個數組,數組中的第8個元素取出來賦值給i。

這個句子也可以寫成i=*(calendar[4]+7);i=*(*(calendar+4)+7)

而p=calendar這個語句就是非法的,因爲calendar是二維數組,而p是指向int的指針。

Obviously,我們需要一個能指向數組的指針。比如int (*ap)[31];

這句話的意思是聲明*ap是一個擁有31個元素的整形數組,而ap就是一個指向這樣的數組的指針。因而我們可以這麼寫:

int calendar[12][31];

int (*monthp)[31];

monthp=calendar..

假如在新年伊始之際,我們需要清空calendar數組,可以用如下兩種形式(or more,anyway)來表示:

int month;
for(month=0;month<12;month++)
{
    int day;
    for(day=0;day<31;day++)
            calendar[month][day]=0;//or *(*(calendar+month)+day)=0;
}

//method 2 in ptr way

int (*monthp)[31];
for(monthp=calendar;monthp<&calendar[12];monthp++)
{
     int *dayp;
     for(dayp=*monthp;dayp<&(*monthp)[31];dayp++)
        *dayp=0
}

 

非數組的指針:假如我們有兩個字符串s,t,希望把他們合成一個字符串r,該怎麼辦?

我們可以藉助庫函數strcpy and strcat,思路好想,但是可能寫起來會有問題:

//錯誤演示
char *r;   //設置一個字符數組
strcpy(r,s);   //想把s複製給r
strcat(r,t);    //然後r後綴一個t

/*想法很好,但是是有問題的,原因是r指向何處是不確定的,我們可以看到,
不僅r得指向一個地址,並且r所指向的空間還得有足夠的內存空間來容納字符串,
根據C的特性,所以需要給r分配一定的空間,比如下面*/

char r[100];
strcpy(r,s);
strcat(r,t); //只要st的內存不要太大,這麼寫van題就不大,
如果我們不能獲知st的相對規模的話,這怎麼辦呢

//malloc啊

char *r;
r=(char*)malloc(strlen(s),strlen(t));
strcpy(r,s);
strcat(r,t);

free(r);

作爲參數的數組聲明

在C語言中,我們沒有辦法直接把一個數組作爲函數參數來傳遞,如果我們使用數組名作爲參數,那麼數組名竟會被立刻轉換爲只想該數組第一個元素的參數,比如啊 char hello[]="hello";

這聲明瞭hello是一個數組,如果把這個數組作爲函數參數傳給一個函數,實際上和把數組的第一個元素的地址傳給函數的作用完全等效,也就是說

printf("%s\n",hello);
和
printf("%s\n",&hello[0]);
是一樣的

因此,將數組當成參數傳給函數毫無意義,c會自動把作爲參數的數組轉換爲相應的指針聲明,也就是說下面倆也完全一樣。

int strlength(cahr s[]){}
和
int strlength(char *s){}

但是extern char *hello[]和extern char hello[];卻有着千差萬別,這個作爲後話

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章