暑期講座遺漏知識點整理一

一、有符號數與無符號數的強制類型轉換問題
    上次遇到一個問題,在比較兩sizeof返回值的時候出現了意想不到的錯誤,原因在於sizeof返回的是無符號類型,所以出現錯誤。
    有符號數和無符號數的區別在於第一位表示正負數,還是數值。換句話說,有符號的二進制數最高位是符號位,剩下的是數值部分的補碼(正數的補碼是其本身,負數的補碼是該數值取反加一)。例如int a = -1;unsign b; b = a;
那麼printf(“%u”,b);結果是4294967295。
二、表達式的副作用
C 語言中,術語副作用是指對數據對象或者文件的修改,序列點是指程序運行中的一個特殊的時間點,在該點之前的所有副作用已經結束,並且後續的副作用還沒發生。C 語句結束標誌——分號(;)是序列點。也就是說,C 語句中由賦值、自增或者自減等引起的副作用在分號之前必須結束。任何完整表達式運算結束的那個時間點也是序列點。所謂完整表達式,就是說這個表達式不是子表達式。而所謂的子表達式,則是指表達式中的表達式。
     經常見到m = 1; n = m+++m++;類似的題目,求最後n的值。這裏 n = m++ + m++ 是完整表達式,而 m++ 是它的子表達式。這個完整表達式運算結束的那一點是一個序列點,int m = 1, n; 中的 ; 也是一個序列點。也就是說,m++ + m++ 位於兩個序列點之間。標準規定,在兩個序列點之間,一個對象所保存的值最多隻能被修改一次。但是我們清楚可以看到,上面這個例子中,m 的值在兩個序列點之間被修改了兩次。這顯然是錯誤的!這段代碼在不同的編譯器上編譯可能會導致 n 的值有所不同。比較常見的結果是 n 的值最後被修改爲 2 或者 3。在此,各位只要記住這是錯誤的,別這麼用就可以了。
三、關於求平均值所引起的思考
 求兩個數的平均值,我想大多數人一定是用(x+y)/2這種方式來求,但是如果
a > INT_MAX,b > INT_MAX,那麼最後平均值我們怎麼實現呢?可以考慮通過位運算求得((x^y)>>1)+(x&y),知道了所謂的答案並不是目的,關鍵在於其中的思考過程,爲什麼不能直接看出問題的本質,又怎麼樣在看出問題的陷阱後及時想出完善的解法值得我們深思,學習不允許半點馬虎的地方,處處應該細心,關注可能出現的問題,同時還要需要牢固的基礎,這樣才能在技術的道路上越走越遠。
四、掃描集
ANSIC 標準向 scanf() 增加了一種新特性,稱爲掃描集(scanset)。掃描集定義一個字符集合,可由 scanf() 讀入其中允許的字符並賦給對應字符數組。掃描集合由一對方括號中的一串字符定義,左方括號前必須綴以百分號。
具體作用是:如果輸入的字符屬於方括號內字符串中某個字符,那麼就提取該字符;如果一經發現不屬於就結束提取。該方法會自動加上一個'\0'到已經提取的字符後面。在“[]”內,還可以加入另外一個字符來修飾它的作用:“^”。這個符號可以理解爲“補集”,即,掃描除方括號之內的其它字符:如果輸入的字符不屬於方括號內字符串中某個字符,那麼就提取該字符;如果一經發現輸入的字符屬於該字符,則結束。爲了簡便,我們可以這樣簡寫[^A-Z]
五、assert斷言
注意:assert是宏,而不是函數。在C的assert.h頭文件中。
assert宏的原型定義在<assert.h>中,其作用是如果它的條件返回錯誤,則終止程序執行,原型定義:
#include <assert.h>
void assert( int expression );
assert的作用是先計算表達式expression,如果其值爲假(即爲0),那麼它先向標準錯誤流stderr打印一條出錯信息,然後通過調用abort來終止程序運行;否則,assert()無任何作用。宏assert()一般用於確認程序的正常操作,其中表達式構造無錯時才爲真值。完成調試後,不必從源代碼中刪除assert()語句,因爲宏NDEBUG有定義時,宏assert()的定義爲空。
使用assert的缺點是,頻繁的調用會極大的影響程序的性能,增加額外的開銷。
在調試結束後,可以通過在包含#include <assert.h>的語句之前插入 #define NDEBUG 來禁用assert調用,示例代碼如下:
#include <stdio.h>
#define NDEBUG
#include <assert.h>


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