3.1 強類型檢查

    強類型檢查選項“-strong”和它的輔助(補充)選項“-index”可以對typedef定義的資料類型進行強類型檢查,以保證只有相同類型之間的變數才能互相賦值,強類型檢查選項strong的用法是:
-strong( flags[, name] ... )
strong選項必須在typedef定義類型之前打開,否則PC-Lint就不能識別typedef定義的資料類型,類型檢查就會失效。flags參數可以是AJXBblf,相應的解釋和弱化字元在表 2 中列出:



























2 強類型檢查strong選項和參數表



A               



對強類型變數賦值時進行類型檢查,這些賦值語句包括:直接賦值、返回值、參數傳遞、初始化
A參數後面可以跟以下字元,用來弱化A的檢查強度:
i   忽略初始化
r   忽略Return語句
p   忽略參數傳遞 
a   忽略賦值操作
c   忽略將常量賦值(包括整數常量、常量字串等)給強類型的情況
z   忽略Zero賦值,Zero定義為任何非強制轉換為強類型的0常量。例如:0L(int)0都是Zero
    但是(HANDLE)0HANDLE是一個強類型的時候就不是Zero(HANDLE *)0也不是例如使用-strong(Ai,BITS)設置,PC-Lint將會對從非BITS類型資料向BITS類型資料賦值的程式碼發出警告,但是忽略 變數初始化時的此類賦值。



X



當把強類型的變數賦指給其他變數的時候進行類型檢查。弱化參數i, r, p, a, c, z同樣適用於X並起相同的作用。



J



選項是當強類型與其他類型進行如下的二進位操作時進行檢查,下面是J的參數:
e   忽略==!=?:操作符
r   忽略>>=<<=
o   忽略+-*/%|&^
c   忽略該強類型與常量進行以上操作時的檢查
z   忽略該強類型與Zero進行以上操作時的檢查


使用忽略意味著不會產生警告資訊。舉個例子,如果Meters是個強類型,那麼它只在判斷相等和其他關係操作時才會被正確地檢查,其他情況則不檢查,在這個例子中使用J選項是正確的。



B



B選項有兩個效果:
     1. 出於強類型檢查的目的,假設所有的Boolean操作返回一個和Type相容的類型,所謂Boolean操作就是那些指示結果為truefalse的操 作,包括前面提到的四種關係運算符和兩種等於判斷符,取反操作符!,二元操作符&&||
     2. 在所有需要判斷Bolean值的地方,如if語句和while語句,都要檢查結果是否符合這個強類型,否則警告。
     例如if(a)...aint時,將產生警告,因為intBolean類不相容,所以必須改為if(a != 0)



b



僅僅假定每一個Bolean類操作符都將返回一個與Type類型相容的返回值。與B選項相比,b選項的限制比較寬鬆。



l



庫標誌,當強類型的值作為參數傳遞給庫函數等情況下,不產生警告。



f



Bb連用,表示抑止對1bit長度的位域是Boolean類型的假定,如果不選該項表示1bit長度的位域被缺省假定為Boolean類型。



 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


    這些選項字元的順序對功能沒有影響。但是AJ選項的弱化字元必須緊跟在它們之後。B選項和b選項不能同時使用,f選項必須搭配B選項或b選項使用,如果 不指定這些選項,-strong的作用就是僅僅聲明type為強類型而不作任何檢查。下面用一段程式碼演示-strong選項的用法:


//lint -strong(Ab,Bool) <選項是以注釋的形式插入程式碼中>
typedef int Bool;
Bool gt(int a, b)
{
  if(a) return a > b; // OK
  else return 0; // Warning
}
子程式碼中Bool被聲明成強類型,如果沒有指定b選項,第一個return語句中的比較操作就會被認為與函數類型不匹配。第二個return語句導致警告 是因為0不是各Bool類型,如果添加c選項,例如-strong(Acb,Bool),這個警告就會被抑制。再看一個例子:
/*lint -strong( AJXl, STRING ) */
typedef char *STRING;
STRING s;
...
s = malloc(20);
strcpy( s, "abc" );


由於mallocstrcpy是庫函數,將malloc的返回值賦給強類型變數s或將強類型變數s傳遞給strcpy時會產生強類型衝突,不過l選項抑制了這個警告。
    強類型也可用於位域,出於強類型檢查的目的,先假定位元域中最長的一個欄位是優勢Boolean類型,如果沒有優勢Boolean或位域中沒有哪個欄位比其他欄位長,這個類型從位域被切開的位置開始成為類型,例如:
//lint -strong( AJXb, Bool )
//lint -strong( AJX, BitField )
typedef int Bool;
typedef unsigned BitField;
struct foo
{
unsigned a:1, b:2;
BitField c:1, d:2, e:3;
} x;
void f()
{
x.a = (Bool) 1; // OK
x.b = (Bool) 0; // strong type violation
x.a = 0; // strong type violation
x.b = 2; // OK
x.c = x.a; // OK
118
x.e = 1; // strong type violation
x.e = x.d; // OK
}


上面例子中,成員ac是強類型Bool,成員deBitField類型,b不是強類型。為了避免將只有一位的位域假設成Boolean類型, 需要在聲明Boolean-strong中使用f選項,上面的例子就應該改成這樣:-strong(AJXbf,Bool)


    另一個強類型檢查選項是indexindex的用法是:
-index( flags, ixtype, sitype [, sitype] ... )
個選項是對strong選項的補充,它可以和strong選項一起使用。這個選項指定ixtype是一個排除索引類型,它可以和Strongly Indexed類型sitype的陣列(或指標)一起使用,ixtypesitype被假設是使用typedef聲明的類型名稱。flags可以是c dc允許將ixtype和常量作為索引使用,而d允許在不使用ixtype的情況下指定陣列的長度(Dimensions)。下面是一個使用index 的例子:
//lint -strong( AzJX, Count, Temperature )
//lint -index( d, Count, Temperature )
// Only Count can index a Temperature
typedef float Temperature;
typedef int Count;
Temperature t[100]; // OK because of d flag
Temperature *pt = t; // pointers are also checked
// ... within a function
Count i;
t[0] = t[1]; // Warnings, no c flag
for( i = 0; i < 100; i++ )
t[i] = 0.0; // OK, i is a Count
119
pt[1] = 2.0; // Warning
i = pt - t; // OK, pt-t is a Count


上面的例子中,Temperature是被強索引類型,Count是強索引類型。如果沒有使用d選項,陣列的長度將被映射成固有的類型:
Temperature t[ (Count) 100 ];
但是,這是個小麻煩,像下面那樣將陣列長度定義成常量更好一些:
#define MAX_T (Count) 100
Temperature t[MAX_T];


這樣做還有一個好處就是同樣的MAX_T還可以用在for語句中,用於限制for語句的範圍。需要注意的是,指向強被索引類型的指標(例如上面的 pt)如果用在[]符號(陣列符號)中也會被檢查類型。其實,無論何時,只要將一個值加到一個指向強被索引類型的指標時,這個值就會被檢查以確認它是一個 強索引類型。此外,強被索引指標如果減去一個值,其結果被認為是平常的強索引,所以下面的例子就不會產生警告:
i = pt - t;

    全站熱搜

    立你斯 發表在 痞客邦 留言(0) 人氣()