ch12_FundamentalDataType

advertisement
Fundamental Data Type
Chapter 12
Number

Don't use "magic numbers", use "defined" constants



Use hard-coded 0s and 1s if you need to




y = x + (float) I
Avoid mixed-type comparisons



for i = 0 to CONSTANT do ...
total = total + 1
Anticipate divide-by-zero errors
Make type conversions obvious


int Array[100] vs. int size = 100; int Array[size]
for i = 0 to 99 do ... vs. for i = 0 to MAX_ENTRIES-1 do ...
If x is a floating-point number and i is an integer, the following test is
almost guaranteed not to work.
if ( i = x ) then ...
Heed your compiler's warnings
Integers

Check for integer division


7/10 does equal 0.7?
Check for integer overflow




overflow is always silent
16 bit --> (-32768, + 32767) or unsigned is 65536
250 * 300=75,000.
But if the maximum integer is 65,535, the answer you'll get is
probably 9464


because of integer overflow (75,000 - 65,536 = 9464).
Check for overflow in intermediate results
Why?
Limit (unsigned 16bits):
65535 or 1111 1111 1111 1111
Too big:
65536 or 1 0000 0000 0000 0000
What's stored:
0 or 0000 0000 0000 0000
stored = value % (limit + 1) or 65536 % (65535 + 1) = 0
Positive limit(signed 16bits):
32767 or 0111 1111 1111 1111
Too big:
32768 or 1000 0000 0000 0000
What's stored:
-32768
1000 0000 0000 0000
0111 1111 1111 1111 (2’s compliment)
+
1
1000 0000 0000 0000
Floating-Point Numbers

Around problem:


With a 32-bit floating-point variable,
1,000,000.00 + 0.1 =1,000,000.00



because 32 bits don't give you enough significant digits to encompass the
range between 1,000,000 and 0.1.
Likewise, 5,000,000.02 - 5,000,000.01 is probably 0.0.
Solutions?




Avoid additions and subtractions on numbers that have greatly
different magnitudes
If you have to add a sequence of numbers that contains huge
differences like this, sort the numbers first, and then add them
starting with the smallest values.
if you need to sum an infinite series, start with the smallest term—
essentially, sum the terms backwards.
This doesn't eliminate round-off problems, but it minimizes them.
Avoid equality comparisons
Solution
Characters and Strings


Avoid magic characters and strings
Use named constants and CONSTANT + 1 for string
allocations


always initialize strings to something



eg. char Name[16]; //bad
#define NAME_LENGTH 15
char Name[NAME_LENGTH + 1] (add 1 for '\0' character)
if nothing else fits, create a NULL string
char String[50] = ""
use calloc rather than malloc


calloc also initializes the acquired memory to 0x00
in C++, always use new for class objects so that constructors are
involve
Characters and Strings –cont’


use strncpy instead of strcpy
use strncmp instead of strcmp

both of the above commands have an extra parameter that
specifies the maximum length of the arguments
Boolean Variables


use them as self-documenting code
eg. if(SearchDone)
eg. if(InputEnd)
use them to split complicated conditional expressions
into simpler terms
eg. InputEnd = feof( ) || ferror( ) ...;
....
if (InputEnd || ..... ||.....) ...
Enumerated Types

Enumerated types are a powerful alternative to shopworn
schemes



“1 stands for red, 2 stands for green, 3 stands for blue…."
This ability suggests several guidelines for using enumerated
types:
Use enumerated types for readability


if chosenColor = 1
you can write more readable expressions like
if chosenColor = Color_Red
Enumerated Types –cont’

Use enumerated types for reliability




With named constants, the compiler has no way of knowing that the
only legal values are Color_Red, Color_Green, and Color_Blue.
The compiler won't object to statements like color =
Country_England or country = Output_Printer.
If you use an enumerated type, declaring a variable as Color, the
compiler will allow the variable to be assigned only the values
Color_Red, Color_Green, and Color_Blue
Use enumerated types for modifiability

If you discover a flaw in your "1 stands for red, 2 stands for green, 3
stands for blue" scheme,


you have to go through your code and change all the 1s, 2s, 3s, and so on.
If you use an enumerated type,

you can continue adding elements to the list just by putting them into the
type definition and recompiling.
Enumerated Types –cont’


Use enumerated types as an alternative to boolean variables
For example, suppose you have a routine



Return true = successfully performed its task
Return false = otherwise.
Later you might find that you really have two kinds of False.




False 1= the task failed and the effects are limited to the routine itself;
False 2= the task failed and caused a fatal error that will need to be
propagated to the rest of the program.
an enumerated type with the values Status_Success, Status_Warning,
and Status_FatalError would be more useful than a boolean with the
values true and false.
This scheme can easily be expanded to handle additional distinctions
in the kinds of success or failure.
Enumerated Types –cont’



Check for invalid values
When you test an enumerated type in an if or case
statement, check for invalid values.
Use the else clause in a case statement to trap invalid
values:
Enumerated Types –cont’


If your language doesn't have enumerated types, You can simulate
them with global variables or classes.
For example, you could use these declarations in Java:
Named Constants
Arrays


bounds check
use arrays sequentially rather than randomly




random accesses in arrays are similar to random gotos in a
program
such accesses tend to be undisciplined, error prone, and hard
to prove correct.
consider using container classes
watch subscript order on multidimensional arrays


Array[i][j] vs Array[j][i] //order!
Using meaningful name for i and j
container classes example
class SafeArray{
private:
enum (size = 100);
int Array[size];
.....
public:
int & operator [ ] (int n);
{
if (n<size)
return Array[n];
else
.... do something dramatic...
}
}
Pointer C++




Pointer usage is one of the most error-prone areas of
modern programming
modern languages like Java, C#, and Visual Basic don't
provide a pointer data type.
Using pointers is inherently complicated, and using them
correctly requires that you have an excellent
understanding of your compiler's memory-management
scheme.
Many common security problems, especially buffer
overruns, can be traced back to erroneous use of
pointers
Pointer C++

Paradigm for Understanding Pointers (two parts: )



a location in memory
a knowledge of how to interpret the contents of that location
Location in Memory



the location in memory is an address
expressed in hexadecimal notation
an address on a 32-bit processor would be a 32-bit value,



0x0001EA40.
the pointer itself contains only this address
If you were to look at the memory in that location, it would be
just a collection of bits. It has to be interpreted to be
meaningful.
Pointer C++

Knowledge of How to Interpret the Contents


interpret the contents of a location in memory is provided by
the base type of the pointer.
If a pointer points to an integer


the compiler interprets the memory location given by the pointer as
an integer.
you can have an integer pointer, a string pointer, and a floating-point
pointer all pointing at the same memory location.

only one of the pointers interprets the contents at that location correctly.
The amount of memory
used by each data type is
shown by double lines
Tips on Pointers

Declare and define pointers at the same time
Tips on Pointers –cont’

Use extra pointer variables for clarity

It's hard enough to figure out what someone is doing with a
linked list without having to figure out


why one genericLink variable is used over and over again or
what pointer->next->last->next is pointing at.
Tips on Pointers –cont’

Draw a picture

Code descriptions of pointers can get confusing. It usually helps to draw a
picture.
Tips on Pointers –cont’

Set pointers to null after deleting or freeing them



A common type of pointer error is the "dangling pointer," use
of a pointer that has been delete'd or free'd.
By setting pointers to null after freeing them, you don't change
the fact that you can read data pointed to by a dangling
pointer.
But you do ensure that writing data to a dangling pointer
produces an error.
Tips on Pointers –cont’

Simplify complicated pointer expressions



complicated pointer expressions are hard to read
if your code contains expressions like p->q->r->s.data
think about the person who has to read the expression
C++-Pointer Pointers

The difference between pointers and references



in C++, both pointers (*) and the references (&) refer
indirectly to an object.
to the uninitiated the only difference appears to be a purely
cosmetic distinction between referring to fields as object->field
vs. object.field.
the most significant differences are that



a reference must always refer to an object,
a pointer can point to null
what a reference refers to can't be changed after the reference
is initialized.
C++-Pointer Pointers

Use pointers for "pass by reference" parameters and use
const references for "pass by value" parameters




C++ defaults to passing arguments to routines by value rather
than by reference.
When you pass an object to a routine by value, C++ creates a
copy of the object, and when the object is passed back to the
calling routine, a copy is created again.
For large objects, that copying can eat up time and other
resources.
Consequently, when passing objects to a routine, you usually
want to avoid copying the object, which means you want to
pass it by reference rather than by value.
C++-Pointer Pointers – cont’

Sometimes, however, you would like to have

the semantics of a pass by reference


the passed object should not be altered
the implementation of a pass by value

passing the actual object rather than a copy
Download