410 likes | 493 Views
Fundamental Data Type. Chapter 12. Number. Don't use "magic numbers", use "defined" constants 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 ... Use hard-coded 0s and 1s if you need to for i = 0 to CONSTANT do ...
E N D
Fundamental Data Type Chapter 12
Number • Don't use "magic numbers", use "defined" constants • 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 ... • Use hard-coded 0s and 1s if you need to • for i = 0 to CONSTANT do ... • total = total + 1 • Anticipate divide-by-zero errors • Make type conversions obvious • y = x + (float) I • Avoid mixed-type comparisons • 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? stored = value % (limit + 1) or 65536 % (65535 + 1) = 0 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.
Characters and Strings • Avoid magic characters and strings • Use named constants and CONSTANT + 1 for string allocations • eg. char Name[16]; //bad #define NAME_LENGTH 15 char Name[NAME_LENGTH + 1] (add 1 for '\0' character) • always initialize strings to something • 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 codeeg. if(SearchDone)eg. if(InputEnd) • use them to split complicated conditional expressions into simpler termseg. 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 = 1you 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:
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