3. PC-Lint code check function
PC-Lint can check many syntax errors and correct logic errors. PC-Lint assigns an error number to most error messages, if the error number is less than 1000, it is assigned to the C language. If the error number is greater than 1000, it is used to indicate the error message of C ++. Table 1 lists the detailed categories of PC-Lint alarm messages:
Table 1 lists the types of PC-Lint alarm messages
Error description |
C |
C ++ |
Alert Level |
Syntax Error |
1-199 |
1001-1199 |
1 |
Internal error |
200-299 |
|
0 |
Fatal Error |
300-399 |
|
0 |
Alert |
400-699 |
1400-1699 |
2 |
Message |
700-800 |
1700-1899 |
3 |
OPTIONAL INFORMATION |
900-999 |
1900-1999 |
4 |
Take the C language as an example. The number "" indicates a syntax error that may be generated by the General compiler. The number "200-299" indicates an internal error in the PC-lint program, which will not appear in the code; -399 refers to a system fatal error caused by memory restrictions. The prompt information displayed in No. 400-999 is classified based on the possibility of hidden code problems: No. 400-699 refers to the alarm information generated when problems may exist in the checked code; the information in 700-899 is less likely to generate errors than the alarm information, but it may still be caused by code problems. IDS 900-999 are optional and will not be checked by default unless you specify them in the options.
PC-Lint/felexlint provides the alarm level setting option-wlevel similar to that of many compilers. Its alarm level is divided into the following levels, and the default alarm level is three levels:
-W0 does not generate information (except for fatal errors)
-W1 only generates error information-no alarm information or other prompt information
-W2 only contains error and alarm information
-W3 generates errors, alarms, and other prompts (this is the default setting)
-W4: generate all information
PC-Lint/felexlint also provides the alarm level setting option-wlib (level) for processing header files of the function library. This option does not affect the alarm level of the C/C ++ source code module. It has the same alarm level as-wlevel, and the default alarm level is 3:
-Wlib (0) does not generate any library information
-Wlib (1) only generate error information (when processing the source code of the Library)
-Wlib (2) generate error and alarm information
-Wlib (3) generate errors, alarms, and other information (this is the default setting)
-Wlib (4) generates all information
There are many types of PC-Lint checks, strong type check, variable value tracking, semantic information, value assignment sequence check, weak definition check, format check, indentation check, const variable check, volatile variable check, and so on. For each check type, PC-Lint has many detailed options to control the check results of PC-lint. There are more than 300 pC-Lint options, which can be placed in comments (insert the code in the form of comments), for example:
/* Lint option1 option2... optional Commentary */The option can have multiple rows
// Lint option1 option2... optional commentary option is only one line (applicable to C ++)
The options must be separated by spaces. The lint command must be in lowercase and followed by/* Or/. spaces are not allowed. If the option consists of parts similar to operators and operands, such as-esym (534, printf, scanf, operator new), the last option is Operator new, there is only one space between operator and new. The PC-Lint option can also be placed in the macro definition. The option takes effect only when the macro is expanded. For example:
# Define divzero (X)/* lint-save-e54 */(X)/0)/* lint-Restore */allow a division of 0 without warning
Next, we will introduce the common and important types of code checks for PC-lint, and give an example of the possible alerts and usage of common options for each check type:
3.1 strong type check
The strong type check option "-strong" and its auxiliary (Supplemental) option "-index" can perform a strong type check on the data types defined by typedef, to ensure that only variables of the same type can be assigned values to each other, the strong type check option strong is used as follows:
-Strong (flags [, name]...)
The strong option must be enabled before typedef defines the type. Otherwise, PC-Lint cannot identify the data type defined by typedef, And the type check will fail. The flags parameters can be a, J, X, B, B, l, and F. The corresponding explanations and weakening characters are listed in table 2:
Table 2 strong type check strong options and parameter table
A |
Type check is performed when values of a strong type variable are assigned. These assignment statements include direct value assignment, return value, parameter transfer, and initialization. Parameter A can be followed by the following characters to weaken the inspection intensity of parameter: I ignore Initialization R ignore Return Statement P ignore parameter transfer A. Ignore the value assignment operation. C ignores the situation where constants (including Integer constants and constant strings) are assigned to a strong type. Z ignores the zero value assignment. Zero is defined as any non-forced conversion to a strongly typed 0 constant. For example, 0l and (INT) 0 are both zero, But (handle) 0 when handle is a strong type, it is not zero. (Handle *) 0 is not set by-strong (AI, BITs). PC-Lint will send an alarm to the code that assigns values to bits data from non-bits data, however, this type of value assignment during variable Initialization is ignored. |
X |
Type check is performed when a strong variable is assigned to another variable. The weakening parameters I, R, P, A, C, and Z are also applicable to the same effect of X. |
J |
The option is to check if the following binary operations are performed for the strong type and Other types. The following is the J parameter: E ignore = ,! = And? : Operator R ignore>,> =, <and <= O ignore +,-, *,/, %, |, &, and ^ C check when the preceding operations are ignored for this strong type and constant Z checks whether this strong type and zero perform the preceding operations. Using ignore means no alert information is generated. For example, if meters is of a strong type, it will be correctly checked only when it judges the operation of equal and other relations. Otherwise, it will not be checked, in this example, the J option is correct. |
B |
Option B has two effects: 1. for the purpose of the strong type check, assuming that all Boolean operations return a type compatible with the type, the so-called Boolean operation is the operations that indicate that the result is true or false, this includes the four Relational operators mentioned above and two equal-to-judgment operators. The inverse operators are used !, Binary operators & |. 2. Check whether the bolean values, such as the if statement and the while statement, are consistent with the bolean values. Otherwise, an alarm is triggered. For example, if (a)... when a is int, an alarm is triggered. Because int is incompatible with the bolean class, it must be changed to if (! = 0 ). |
B |
It is assumed that every bolean operator will return a type-compatible return value. Compared with option B, option B has relatively loose restrictions. |
L |
Library flag. When a strong value is passed as a parameter to a library function, no alert is generated. |
F |
When used with B or B, it indicates that the bit field of 1 bit length is boolean. If this parameter is not selected, the bit field of 1 bit length is assumed to be boolean by default. |
The character sequence of these options does not affect the function. However, the weakened characters of option A and option J must follow them. Option B and option B cannot be used at the same time. option F must be used with option B or option B. If you do not specify these options, -Strong declares that type is a strong type without any check. The following code demonstrates the usage of the-strong option:
// Lint-strong (AB, bool) <the option is inserted into the code as a comment>
Typedef int bool;
Bool gt (int A, B)
{
If (a) Return A> B; // OK
Else return 0; // warning
}
In the example code, bool is declared as a strong type. If option B is not specified, the comparison operation in the first return statement is considered to be different from the function type. The second return statement causes an alarm because 0 is not of the bool type. if you add the C option, for example,-strong (Acb, bool), this alarm will be blocked. Let's look at another example:
/* Lint-strong (ajxl, string )*/
Typedef char * string;
String S;
...
S = malloc (20 );
Strcpy (S, "ABC ");
Since malloc and strcpy are library functions, assigning the return value of malloc to strong variable s or passing strong variable s to strcpy produces a strong type conflict. However, the L option disables this alarm.
Strong data types can also be used for bit fields. For the purpose of strong data type check, the longest field in the first false position domain is the dominant boolean type, if there is no advantage of Boolean or no field in the bit field is longer than other fields, this type starts from the position where the bit field is cut and becomes a "scattered" type. For example:
// 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
}
In the above example, members A and C are strongly typed bool, members D and E are bitfield, and B is not strongly typed. To avoid assuming that only one bit field is of the boolean type, you need to use the f option in the-strong statement of Boolean. The above example should be changed to-strong (ajxbf, bool ).
Another strong-type check option is index, which is used as follows:
-Index (flags, ixtype, sitype [, sitype]...)
This option is a supplement to the strong option, which can be used with the strong option. This option specifies that ixtype is an excluded index type. It can be used with an array (or pointer) of the stronugly indexed type sitype. ixtype and sitype are assumed to be type names declared using typedef. Flags can be C or D, and C can use ixtype and constant as indexes, while D can specify the length of the array (dimensions) without ixtype ). The following is an example of using 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
In the above example, temperature is of the strongly indexed type, and count is of the strongly indexed type. If the D option is not used, the array length is mapped to an inherent type:
Temperature T [(count) 100];
However, this is a little troublesome. It is better to define the array length as a constant as follows:
# Define max_t (count) 100
Temperature T [max_t];
Another advantage is that max_t can also be used in for statements to limit the scope of for statements. Note that a pointer to the strongly indexed type (for example, the above pt) will also be checked if it is used in the [] symbol (array symbol. In fact, whenever you add a value to a pointer pointing to the strongly indexed type, the value will be checked to confirm that it is a strongly indexed type. In addition, if a value is subtracted from the index pointer, the result is regarded as a normal strong index, so the following example will not generate an alarm:
I = Pt-T;
3.2 variable value tracking
3.2.1 variable value initialization tracking
Early variable value tracking techniques primarily track variable value initialization, And the lint messages related to variable initialization are mainly 644,645 ("variables may not be initialized "), 771,772 ("unreliable initialization"), 530 ("uninitialized"), and 1401-1403 ("member... not initialized "). The following code is used as an example:
If (a) B = 6;
Else c = B; // message 530
A = C; // 645 message
If neither B nor C is initialized before, PC-Lint will report that B is not initialized (when assigning values to C) and C may not be initialized (when a is assigned a value) messages. The while and for loop statements are slightly different from the above if statements. Compare the following code:
While (n --)
{
B = 6;
...
}
C = B; // 772 message
If B is not initialized before use, the message that B may not be initialized is reported here (when C is assigned a value ). The reason for this difference is that the program designer may know that such a loop is always executed at least once. On the contrary, it is difficult for the program designer to determine whether the if statement is always executed. If so, such an if statement is redundant and should be removed. The while statement is similar to the IF statement. See the following example:
Switch (k)
{
Case 1: B = 2; break;
Case 2: B = 3;
/* Fall through */
Case 3: A = 4; break;
Default: Error ();
}
C = B; // 645 message
Although B is assigned a value in two different places, it is still possible that B is not initialized. Therefore, when B is assigned to C, messages that may not be initialized are generated. To solve this problem, you can assign a default value to B before the switch statement. In this way, the PC-Lint will not generate alarm messages, but we also lose the opportunity to let the PC-Lint check for variable initialization problems caused by subsequent code modifications. A better way is to modify the case statement that does not assign a value to B.
If the error () statement indicates that "impossible to happen" occurs, we can let PC-Lint know that this section is actually not executable. The following code indicates this:
Switch (k)
{
Case 1: B = 2; break;
Case 2:
Case 3: B = 3; A = 4; break;
Default: Error ();
/* Lint-unreachable */
}
C = B;
Note: Here-unreachable should be placed behind error (), before break. Another way to generate a "not initialized" alarm is to pass a pointer to free (or use a similar method ). For example:
If (n) Free (P );
...
P-> value = 3;
When P is accessed, messages that may not be initialized by P are generated. For a GOTO statement, the forward goto may produce uninitialized messages, and the backward goto will be ignored.
If (a) goto label;
B = 0;
Label: c = B;
When you use uninitialized variable check in a large project, some error reports may be generated. A large part of this report comes from a poor programming style, or includes the following structure:
If (x) initialize y
...
If (x) use y
In this case, you can assign an initial value to Y, or use option-esym (644, Y) to disable the initialization check on variable Y.
3.2.2 variable value tracking
Variable value tracking technology collects information from Value assignment statements, initialization, and condition statements. By default, function parameters are within the correct range, an alarm is generated only when the information that can be collected from the function is inconsistent with this information. Messages related to variable value tracking include:
(1) access address out-of-bounds message (Message 415,661,796)
(2) Message division by 0 (54,414,795)
(3) incorrect use of NULL pointer (413,613,794)
(4) Invalid Pointer creation error (416,662,797)
(5) redundant Boolean value test (774)
See the following example:
Int A [10];
Int F ()
{
Int K;
K = 10;
Return a [k]; // warning 415
}
This statement generates a warning 415 (access out-of-bounds pointer through '['), because PC-Lint saves the value assigned to K and then makes a judgment when K is used. If we make a slight modification to the above example:
Int A [10];
Int F (int n)
{
Int K;
If (n) k = 10;
Else K = 0;
Return a [k]; // warning 661
}
In this way, an alarm 661 is triggered (access to the cross-border pointer may be triggered ). The possible reason is that not all paths assign 10 to K. PC-Lint not only collects value assignment statements and initialization, but also collects value information from condition statements. For example:
Int A [10];
Int F (int K, int N)
{
If (k> = 10) A [0] = N;
Return a [k]; // warning 661 -- k cocould be 10
}
Here, the 661 alarm is still generated because PC-Lint detects that when K is used, the value of K is greater than or equal to 10. In addition, for a function, it always assumes that K is correct, and the program user knows what they want to do, so the following statement will not generate an alarm:
Int A [10];
Int F (int K, int N)
{Return a [K + N];} // no warning
The same as checking that variables are not initialized, you can also check whether the values of variables are correct. For example, if none of the loops in the following example are run, K may be out of the range. At this time, message 796 is generated (the foreseeable address access is out of bounds ).
Int A [10];
Int F (int n, int K)
{
Int m = 2;
If (k> = 10) m ++; // hmm -- So k cocould be 10, eh?
While (n --)
{M ++; k = 0 ;}
Return a [k]; // info 796--K cocould still be 10
}
The following example demonstrates the possible use of the NULL pointer:
Int * F (int * P)
{
If (p) printf ("/N"); // so -- p cocould be null
Printf ("% d", * P); // warning
Return P + 2; // warning
}
Two alarms are generated here, because the NULL pointer may be used. Obviously, these two statements should be within the scope of the IF statement. To make your program more robust, you may need to turn on the pointer-parameter-may-be-null switch (+ FPN ). This option assumes that all pointers passed to the function may be null. The array boundary value is detected at a high level, that is
Int A [10];... A [10] = 0;
It is detected, but a [-1] cannot. Two messages in PC-Lint are related to the cross-border pointer check. One is the creation of cross-border pointers, and the other is the access of cross-border pointers, that is, the value is obtained through cross-border pointers. In ansi c ([1] 3.3.6), you can create a pointer that points to a unit beyond the end of the array. For example:
Int A [10];
F (a + 10); // OK
F (a + 11); // Error
However, the two pointers created above are inaccessible, for example:
Int A [10], * P, * q;
P = a + 10; // OK
* P = 0; // warning (Access Error)
P [-1] = 0; // no warning
Q = p + 1; // warning (creation error)
Q [0] = 0; // warning (Access Error)
The Boolean condition check is not as strict as the pointer check, but it generates an alarm for the Boolean condition of the constant truth, for example:
If (n> 0) n = 0;
Else if (n <= 0) n =-1; // info 774
The above code generates an alarm (774), because the second condition check is genuine and can be ignored. This type of redundant code does not cause problems, but it is usually generated because of a logical error or a possible sign of an error, and requires a detailed check.
3.2.3 use assert for remediation
In some cases, although we can know the exact value based on the code, PC-Lint cannot obtain the range of variable values in all cases. In this case, some error alarms are generated, we can use the assert statement to increase the value range of the variable to suppress the generation of alarm information for these errors. The following is an example:
Char Buf [4];
Char * P;
Strcpy (BUF, "");
P = BUF + strlen (BUF); // P is 'possibly' (BUF + 3)
P ++; // P is 'possibly' (BUF + 4)
* P = 'a'; // warning 661-possible out-of-bounds reference
PC-Lint cannot know the value of the variable in all circumstances. In the above example, the statements that generate alarms do not actually cause any harm. We can directly use
* P = 'a'; // lint! E661
To suppress alarms. In addition, we can also use the assert tool to fix this problem:
# Include <assert. h>
...
Char Buf [4];
Char * P;
Strcpy (BUF, "");
P = BUF + strlen (BUF );
Assert (P <BUF + 3); // P is 'possibly' (BUF + 2)
P ++; // P is 'possibly' (BUF + 3)
* P = 'a'; // No problem
Assert is an empty operation when ndebug is defined, so it is necessary to ensure that this macro is not defined when Lint is performed.
To make assert () and the assert. H that comes with your compiler produce the above effect, you need to add an option to the compilation option file. For example, suppose assert is implemented through the following compiler macro definition:
# Define assert (p )? (Void) 0: _ (...))
Considering that _ A () will pop up a message and will not return it, the option to be added is:
-Function (exit, _)
This option passes some non-return features of the exit function to the _ a function. As the selection result, the compiler may implement assert as a function, for example:
# Define assert (k) _ assert (K ,...)
To let PC-Lint know that _ assert is an Assert function, you need to use the-function (_ assert, _ assert) option or-function (_ assert (1 ), _ assert (1) option to copy the semantics of the _ assert () function
Many compiler compilation option files already have these options. If not, you can copy an assert. h file to the PC-Lint directory (this directory uses the-I option, and the file search sequence takes precedence over the header file directory of the compiler ).
3.2.4 function variable tracking
The function value tracking function of PC-Lint tracks variable values that will be passed to the function (as function parameters). When a function is called, these values are used to initialize function parameters. This tracking function is used to determine the return value and record additional function calls. Of course, it can also be used to detect errors. Test the following sample code:
T1.cpp:
1 int F (INT );
2 int g ()
3 {return F (0 );}
4 int F (int n)
5 {return 10/N ;}
In this example, when F () is called, 0 is used as the parameter, which will lead to a zero Division Error for the 10/n statements that are originally normal, use the command Lin-u t1.cpp to get the following output:
--- Module: t1.cpp
During Specific walk:
File t1.cpp line 3: F (0)
T1.cpp 5 Warning 414: possible division by 0 [Reference: file t1.cpp: Line 3]
The first thing you notice is the phrase "during specific walk", followed by the location of the function call, the function name and parameters, and the error message. If the error message contains a missing error line during error reproduction and an indication to mark the error location, this is because the code (called Function Code) has passed when the error is detected. Change the positions of the two functions as follows:
T2.cpp:
1 int F (int n)
2 {return 10/N ;}
3 int g ()
4 {return F (0 );}
In this case, no warning will be triggered because F (0) is in the fourth line and the code of function f () has passed, in this case, you need to introduce the multi-pass option. If you use the Lin-u-passes (2) t2.cpp command in the preceding example, the output is:
--- Module: t2.cpp
/// Start of pass 2 ///
--- Module: t2.cpp
During Specific walk:
File t2.cpp line 4: F (0)
T2.cpp 2 warning 414: possible division by 0 [Reference: file t2.cpp: Line 4]
Using the-passes (2) option will check the code twice. Some operating systems do not support using-passes (2) in command lines. For such systems, you can use-passes = 2 or-passes [2] instead. It can be seen through lengthy information that, starting with pass 2, no alarm information is generated during the first check. The error message obtained this time is different from the previous one. In some cases, we can infer the returned value of a specified function call and obtain at least some attributes of the returned value. The following modules are used as an example:
T3.cpp:
1 int F (int n)
2 {return n-1 ;}
3 int g (int n)
4 {return N/F (1 );}
Run the Lin-u-passes (2) t3.cpp command to obtain the following output information:
--- Module: t3.cpp
/// Start of pass 2 ///
--- Module: t3.cpp
{Return N/F (1 );}
T3.cpp 4 warning 414: possible division by 0 [Reference: file t3.cpp: lines 2, 4]
The first check shows that the parameter passed by calling function f () is 1, and the second check first processes function f (). We infer that this parameter will result in the returned result being 0, when the second check starts to process the function g (), an error of division by 0 is generated. It should be noted that this information did not appear before the phrase "during specific walk" because the error was detected during the normal processing of function g, at this time, the value specified for the function g () is not used. The specified function call can generate additional function calls. If we pass enough times, this process may happen repeatedly. refer to the following code:
T4.cpp:
1 int F (INT );
2 int g (int n)
3 {return F (2 );}
4 int F (int n)
5 {return n/f (n-1 );}
The denominator F (n-1) of the fifth line will not cause suspicion until we realize that F (2) calls will lead to F (1) calls, and F (0) will eventually be called ), the final returned value is 0. Use the following command line:
Lin-u-passes (3) t4.cpp,
The output result is as follows:
--- Module: t4.cpp
{Return F (2 );}
T4.cpp 3 info 715: symbol 'N' (line 2) not referenced
/// Start of pass 2 ///
--- Module: t4.cpp
/// Start of pass 3 ///
--- Module: t4.cpp
During Specific walk:
File t4.cpp line 3: F (2)
File t4.cpp Line 5: F (1)
T4.cpp 5 Warning 414: possible division by 0 [Reference: file t4.cpp: Lines 3, 5]
The possible division error is detected only after three times of processing. For more information, see this option-specific_wlimit (n ). It should be noted that the specified call sequence, F (2), F (2), appears as the preface of the alarm information.
3.3 check the assignment order
When the value of an expression depends on the order of value assignment, an alarm of 564 is triggered. This is a common problem in C/C ++, but few compilers will analyze this situation. For example
N ++ n
This statement is ambiguous. When the + operation on the left is executed first, its value will be greater than the value first executed on the right. A more common example is as follows:
A [I] = I ++;
F (I ++, N + I );
In the first example, it seems that the auto-increment operation should be executed after array index calculation, but if the value assignment operation on the right is executed before the value assignment operation on the left, the auto-increment operation is executed before the array index calculation. Although the value assignment operation seems to indicate an operation order, it does not actually exist. The second example is ambiguous because the order in which function parameter values are calculated is not guaranteed. The operators that guarantee the order of values are Boolean and (&) or (|) and conditional values (? :) And comma (,), so:
If (n = f () & n> 10 )...
This statement is correct, and:
If (n = f () & n> 10 )...
An alarm is generated.
3.4 weak definition check
The weak definition includes macro definition, typedef name, declaration, structure, union, and enumeration type. Because these things may be too defined and not used in the module, PC-Lint has a lot of messages to check these problems. Messages 749-769 and 1749-1769 of PC-Lint are reserved for weak definition prompts.
(1) When no reference in the file # include header file is used by this file, PC-Lint will issue a 766 alarm.
(2) In order to avoid a header file becoming too large and bloated and prevent redundant declarations, when the object declaration in the header file is not referenced by the external module, PC-Lint will issue a 759 alarm.
(3) When a variable or function is used only within the module, PC-Lint generates a 765 alarm to prompt that the variable or function should be declared as static.
If you want to use PC-lint to check code that has not been checked before, you may want to disable the alarm information. Of course, if you only want to view the header file exceptions, you can try this command:
Lint-W1 + e749 + E? 75? + E? 76? ...
3.5 format check
PC-Lint checks the format conflicts between printf and scanf (and their families). For example:
Printf ("% + C ",...)
A 566 alarm will be generated because the plus sign is only useful for numeric conversion. If there are more than one hundred such combinations, an alarm will be generated. The Compiler usually does not mark these contradictions, other alarms complain about bad formats, which are 557 and 567. We follow the rules set up by ansi c, and, more importantly, we also mark incorrectly sized formats (including alarms 558,559,560 and 561 ). For example, in % d format, int and unsigned int are allowed, but double and long (if long is longer than INT) are not supported. Similarly, scanf must point to the correct object size. If the parameter type (not the size) is inconsistent with the format, an alarm of 626 and 627 is generated. -The printf and-scanf options allow users to specify functions similar to the family of printf or scanf functions.-printf_code and-scanf_code can also be used to describe non-standard % codes.
3.6 indent check
According to the indentation problem in the code, PC-Lint will also generate corresponding alarms, because a large part of the indentation problem is caused by poor code structure or missing braces. For example:
If (...)
If (...)
Statement
Else statement
Obviously, here Else corresponds to the first if statement, and here the compiler maps it to the second if statement. PC-Lint generates an alarm for this situation. There are three alarms related to this indentation check: 725 (no positive indentation), 525 (negatively indented from), and 539 (did not distinct CT positive indentation from location) to check the indentation, first set the number of spaces corresponding to the tab key in the file. The default value is 8 spaces. You can use the-T # option to modify this parameter. For example,-T4 indicates that the tab key occupies four spaces. In addition, the indentation check is also related to the code encoding format policy and requires necessary adjustments.
3.7 const variable check
For the const variable check, PC-Lint is fully supported. Using the const variable is very helpful for improving the quality of the Code. See the following example in detail:
Char * strcpy (char *, const char *);
Const char c = 'a ';
Const char * P = & C;
Void main ()
{
Char Buf [100];
C = 'B ';
* P = 'C ';
Strcpy (p, Buf );
...
Here, both C and * P point to static variables and cannot be modified. The above code obviously violates this rule and produces error (11). In addition, when P is passed into strcpy as the first parameter, an alarm of 605 (increase in Pointer capability) is generated ), when the Buf is passed into the strcpy function as the second parameter, an alarm 603 (symbol 'symbol' (location) not initialized) is generated because the Buf is not initialized, the second parameter of static variables cannot be initialized in the strcpy function.
3.8 volatile variable check
For the volatile variable check, there is such a rule in PC-lint. If two identical volatile variables are used in an expression at the same time, a 564 alarm is triggered, this will cause the order of values.
Volatile char * P;
Volatile char F ();
N = (f () <8) | f ();/* warning 564 */
N = (* P <8) | * P;/* warning 564 */