3.1 強類型檢查
強類型檢查選項“-strong”和它的輔助(補充)選項“-index”可以對typedef定義的資料類型進行強類型檢查,以保證只有相同類型之間的變數才能互相賦值,強類型檢查選項strong的用法是:
-strong( flags[, name] ... )
strong選項必須在typedef定義類型之前打開,否則PC-Lint就不能識別typedef定義的資料類型,類型檢查就會失效。flags參數可以是A、J、X、B、b、l和f,相應的解釋和弱化字元在表 2 中列出:
表 2 強類型檢查strong選項和參數表 | |
A | 對強類型變數賦值時進行類型檢查,這些賦值語句包括:直接賦值、返回值、參數傳遞、初始化 。 |
X | 當把強類型的變數賦指給其他變數的時候進行類型檢查。弱化參數i, r, p, a, c, z同樣適用於X並起相同的作用。 |
J | 選項是當強類型與其他類型進行如下的二進位操作時進行檢查,下面是J的參數: 使用忽略意味著不會產生警告資訊。舉個例子,如果Meters是個強類型,那麼它只在判斷相等和其他關係操作時才會被正確地檢查,其他情況則不檢查,在這個例子中使用J選項是正確的。 |
B | B選項有兩個效果: |
b | 僅僅假定每一個Bolean類操作符都將返回一個與Type類型相容的返回值。與B選項相比,b選項的限制比較寬鬆。 |
l | 庫標誌,當強類型的值作為參數傳遞給庫函數等情況下,不產生警告。 |
f | 與B或b連用,表示抑止對1bit長度的位域是Boolean類型的假定,如果不選該項表示1bit長度的位域被缺省假定為Boolean類型。 |
這些選項字元的順序對功能沒有影響。但是A和J選項的弱化字元必須緊跟在它們之後。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" );
由於malloc和strcpy是庫函數,將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
}
上面例子中,成員a和c是強類型Bool,成員d和e是BitField類型,b不是強類型。為了避免將只有一位的位域假設成Boolean類型, 需要在聲明Boolean的-strong中使用f選項,上面的例子就應該改成這樣:-strong(AJXbf,Bool)。
另一個強類型檢查選項是index,index的用法是:
-index( flags, ixtype, sitype [, sitype] ... )
這 個選項是對strong選項的補充,它可以和strong選項一起使用。這個選項指定ixtype是一個排除索引類型,它可以和Strongly Indexed類型sitype的陣列(或指標)一起使用,ixtype和sitype被假設是使用typedef聲明的類型名稱。flags可以是c或 d,c允許將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;
留言列表