4 Types
强类型检查一般会暴露很多程序问题。相对于传统的编译器,Splint对于C的
基本类型的检查更严格,更灵活,而且,Splint也提供了对Boolean类型的支
持。另外,用户可以定义抽象数据类型(提供信息隐藏)。
4.1 Built in C Types
Splint对C的内嵌类型提供更严格的检查。对于char和enum类型,它们可以被
当作独特类型(distinct type)进行检查;不同的数值类型的检查也很严格。
4.1.1 Characters
基本类型char可以被当作一个独特类型。如果char作为一个独特类型使用,会
检测到一些很常见的错误,如把一个int赋给char。
+charint标志可以被用来检查一些使用了int和char互相转化的早期程序。如果
打开了charint,表示char和int类型没区别。如果想让char和int保持独特类型,
但是又允许char用来索引数组,用+charindex。
4.1.2 Enumerators
标准C把用户定义的枚举类型当作整形处理。任意整数都可以赋给一个枚举类型,
不管它是否作为一个枚举成员。Splint把自定义枚举类型当作独特类型处理。如
果一个非枚举类型赋给了一个枚举类型,Splint会报告错误;如果一个枚举类型
作为了算术操作的操作数,也会报告错误。当打开了enumint标志的时候,enum和
int类型可以互相转化。同样,enumindex标志打开的话,枚举类型可以用来索引
数组。
4.1.3 Numeric Types
当数值类型不正确使用时,Splint将报告错误。在最严格的检查条件下,Splint
将在数值类型不严格匹配时就报告错误。如果打开了relax-quals标志,只有那些
矛盾(指可能改变值)的使用,才会报告错误。比如,如果一个int变量赋给了一个
long类型变量(或者作为long参数传递),在relax-quals打开的情况下,Splint不
会报告错误,因为一个long变量有足够位去容纳一个int变量,不会使其值丢失。
相反的,如果一个long变量赋给一个int变量,将报告一个错误,因为int类型没
有足够位去容纳一个long值。
类似的,如果一个有符号值赋给一个无符号值,Splint会报告错误,因为无符号
类型不能正确的代替所有的有符号值。如果打开了+ignore-signs标志,检查时将
在类型比较时忽略所有的标志位(这个不推荐,因为它会阻止报告一个bug,但是
可能当要快速检查一定量的早期代码时有用)。
4.1.4 Arbitrary Integral Types
一些类型可以被声明成整型类型,但是其具体类型可能独立实现。比如,标准库
中声明了类型size_t,ptr_diff和wchar_t,但是没有强制它们的类型,只是限制为
integral类型。程序里可以把它们当作整型(如,可以对两个size_t操作数作加法)
,但是不能把它们当作特殊类型(如,long unsigned)
Splint支持3种不同的任意整型(arbitrary integral types):
/*@integraltype@*/
一种整数类型。其真实类型可以是short,int,long,unsigned short,unsigned或
unsigned long的一种。
/*@unsignedintegraltype@*/
一种无符号整数类型。其真实类型可以是unsigned short,unsigned或unsigned
long的一种。
/*@signedintegraltype@*/
一种有符号整数类型。其真实类型可以是short,int或long的一种。
如果代码依赖于一个整数类型的实际类型,Splint将报告错误。match-any-integral
标志放宽了检查,允许一个arbitrary整数类型去匹配任何整数类型。
还有其它的标志可以设置arbitrary整型为一个具体类型。这些仅用于那些平台相关
性不是很重要(不能的类型表示不重要)的情况下。long-integral标志和
long-unsigned-integral标志把与/*@integraltype@*/有关的类型分别设置为unsigned
long和long。long-unsigned-unsigned-integral标志把与/*@signedintegraltype@*/
相关的类型设置为long。long-signed-integral标志把与/*@signedintegraltype@*/
相关的类型设置为long。
4.2 Boolean Types
ISO99前的C语言标准中不支持Boolean类型-一个比较操作符的结果是一个整型,测
试表达式的结果也不会有类型检查。C99加入了Boolean类型(_Bool和bool,true和
false宏定义在stdbool.h里),但是没有加强类型检查。Splint支持Boolean类型检查。
通过引入独立的Boolean类型和强类型检查,很多普通错误都可以被检测出。
对于if,while,for语句中的测试表达式,或者&&,||,!operator的操作数,Splint会
检查其是否是Boolean。如果一个测试表达式的类型不是Boolean类型,Splint将根据
其类型和标志设置来给出警告。如果测试表达式里有指针,-predboolptr将禁止警告(
这个可用于当一个非空指针就是一个表达式的情况下)。如果表达式类型是int,警告
可以由-pred-bool-int阻止。对于其他的类型,除非设置了-pred-bool-others,不然
Splint都将给出警告。关系函数,比较函数和一些标准库函数都声明为Boolean类型。
一个常见错误就是把'='代替'==',Splint中pred-assign标志可以用来控制这类赋值
表达式的报告。可以通过在表达式两边增加额外的括号来阻止报告这些信息。
我们可以用-booltype<name>标志选择一个类型名字来代替Boolean类型。这里没有默
认的Boolean类型,尽管按照约定使用了bool。TRUE和FALSE被假设为代表true和false
布尔类型。如果想改变true和false的名字,可以用-booltrue和-boolfalse。(Splint
中包含了一份bool的实现(在lib/bool.h)。但是,布尔类型的检查并不一定需要用到这
个实现。)
下面是一个例子。
alex@sishen:~/tmp$ cat bool.c
#include "/usr/share/splint/lib/bool.h"
int f(int i, char *s, bool b1, bool b2)
{
4 if (i = 3)
5 return b1;
6 if (!i || s)
7 return i;
8 if (s)
9 return 7;
10 if (b1 == b2)
11 return 3;
12 return 2;
}
alex@sishen:~/tmp$ splint bool.c +predboolptr
bool.c:4:7: Test expression for if is assignment expression: i = 3
The condition test is an assignment expression. Probably, you mean to use ==
instead of =. If an assignment is intended, add an extra parentheses nesting
(e.g., if ((a = b)) ...) to suppress this message. (Use -predassign to
inhibit warning)
bool.c:4:7: Test expression for if not boolean, type int: i = 3
Test expression type is not boolean or int. (Use -predboolint to inhibit
warning)
bool.c:5:12: Return value type bool does not match declared type int: b1
Types are incompatible. (Use -type to inhibit warning)
bool.c:6:8: Operand of ! is non-boolean (int): !i
The operand of a boolean operator is not a boolean. Use +ptrnegate to allow !
to be used on pointers. (Use -boolops to inhibit warning)
bool.c:6:13: Right operand of || is non-boolean (char *): !i || s
bool.c:8:7: Test expression for if not boolean, type char *: s
Test expression type is not boolean. (Use -predboolptr to inhibit warning)
bool.c:10:7: Use of == with boolean variables (risks inconsistency because of
multiple true values): b1 == b2
Two bool values are compared directly using a C primitive. This may produce
unexpected results since all non-zero values are considered true, so
different true values may not be equal. The file bool.h (included in
splint/lib) provides bool_equal for safe bool comparisons. (Use -boolcompare
to inhibit warning)
Finished checking --- 7 code warnings
|
本来答应daojian师兄一起去夜逛西湖的, 却在最后收到短信
说要攀登老和山...
其实当时正在跟fit,zuric,shadowboy,caigoal,hocking一
起dpj, 这里感谢fit gg的bg, ^_^ 而且,dpj时还遇到了
mazha,rhythmbox,andyfires,madog等偶像,真是不需此fb阿,
哈哈.
远了远了, 拉回来了, 想想自己来yq后就没有去过老和山,再
加上已答应daojian, 就一起去了. 当时00:20...
一群没经验的人... 在毫无准备的情况下就上了山... 现在
回想起来,没带手电了,没带水了,恩恩,一堆没带. 不过,倒带
了酒了,还有点吃的,还是要感谢daojian gg的准备. :)
山路难走, 尤其是夜路. 不过, 树影和石阶交错相映,置身其
中, 如虚如幻. 从来没有看过杭州的夜景,站在老和山顶,眺眼
远望: 美, 就在身边! 越夜, 雾越大. 往下看去, 如置身云间,
人神合一了, 哈哈. 老和山顶, 谈理想谈人生, 听daojian
激扬文字, 偷学了很多, lol~~
这里bs一下老和山的台阶.... 一点都没规律, 一会是大台阶,
一会是小台阶. 下山时, 小心翼翼, 一点一点拖着脚过, 就怕
直接滚下来, 提前去见周公了... >_< 还好, 不死凤凰就是
不死凤凰, 还是从地狱回来了...
第一次深夜登山, 第一次座山观月, 很多第一次~~~
困了, 睡觉去... -_-||
|