< .Net Type, Variable & Operator 1 | Main | .Net Type, Variable & Operator 3 >


 

 

Data Types, Variables and Operators 2

 

 

 

 

 

The discussion and the codes used supposed to be based on the new C++ .NET. The following are the topics in this part.

  1. Arrays

  2. Pointers

  3. References

  4. Constants

  5. Enumerations

  6. Typedefs

 

Arrays

 

An array is a collection of data-storage locations, each of which holds the same type of data such as all integers or all doubles. Arrays are very useful when you want to represent a collection of values, such as the number of days in each month or the names of company employees. Each storage location is called an element of the array. Elements of the array are accessed by referring to an offset from the array name. The array elements start at zero and continue up to one less than the array bound:

// Declare an array of ten integers.

int   nArray[10];

int   x;

// The first element in the array starts at the offset 0

nArray[0] = 23;

// The last element in the array starts at the offset 9

nArray[9] = 21;

x = nArray[0];

Writing past the end of the array is a serious problem and the cause of many bugs in C++ programs. When accessing an array element, the compiler calculates the offset from the start of the array. If you’re writing to an array element and you give an invalid index so that the calculated offset is beyond the end of the array, the compiler will overwrite whatever happens to be in that memory location.

 

Pointers

 

A pointer is a variable that holds the memory address of another variable or function, which means that you can use a pointer to refer indirectly to a variable. Why are pointers useful? The first, and most pragmatic, reason is that they have been part of the C family of languages right since the start and they’re very widely used, so you’ll need to know something about them. There are many other reasons though, and we’ve summarized a couple of the most important ones in this note.

First, pointers are one of the main ways that arguments are passed to functions. Arguments are usually passed by value, as a copy, so you can’t modify the value and expect it to get back to the calling code. Pointers let you pass arguments in such a way that you can modify them. Second, some operations on series of data, such as values in arrays, can be performed very efficiently using pointers. Although a pointer variable contains an address and therefore can store a memory address of any data type, pointer variables are declared to be data type specific. A pointer to an integral data type (int) can’t store the address of a double. The pointer variable is declared in the same way as the data type variable, but the pointer operator * (an asterisk) is appended to the data type:

int* pi;           // pointer to an int

double* pd;        // pointer to a double

char* pc;          // pointer to a char

Every variable has an address, and that address can be obtained using the address of operator, which is an ampersand (&). The address of the variable can be stored in a pointer variable, and using that pointer, the contents of that variable can be manipulated by using the dereference operator * (an asterisk):

int x = 10, y = 0;

int* pX = NULL;  // Declare an integer pointer.

pX = &x;         // Store the address of the integer variable x.

y = *pX;         // Use the dereference operator to assign the

                 // value of x to y.

*pX = 20;        // Use the dereference operator to assign 20 to x.

In the last two lines of the code, *pX can be read as “what pX points to”. It might seem confusing that the asterisk is used for both the pointer operator and the dereference operator. You’ll find, however, that the pointer operator is only used when declaring variables, and the dereference operator is used in code. So it is obvious which operator an asterisk represents.

 

References

 

A reference variable is an alias for another variable. All reference variables must be initialized when declared. From then on, any changes made to the referenced variable will be made to the aliased variable. Reference variables are particularly important when passing variables to functions; this topic will be covered in more detail later, but here’s an example:

int    x = 10;

int&   y = x;   // declare y as reference to x.

y = 4;          // Changes the value of x to 4.

Constants

 

Like variables, constants are named data-storage locations. However, unlike a variable, the value of a constant can’t be changed after it has been declared. It has to be initialized when it’s created and can’t be assigned a new value later. C++ has two types of constants: literal and symbolic. A literal constant is simply a value typed into the program. The statements in the following code assign the literals 40 and Dog to the respective variables NoOfEmployees and strName:

NoOfEmployees = 40;

strName = "Dog";

A symbolic constant is a constant that is represented by a name. It is defined in exactly the same way as a variable, but the qualifier must start with the keyword const and the variable must be initialized. After declaration, the constant name can be used anywhere a variable of that type can be used, as shown here:

const unsigned long NoOfFullTimeEmployees = 49;

const unsigned long NoOfPartTimeEmployees = 234;

unsigned int NoOfEmployees;

NoOfEmployees = NoOfFullTimeEmployees + NoOfPartTimeEmployees;

There are a couple of advantages to using symbolic constants rather than literal ones:

  1. The symbolic names make the program more readable. The symbolic constant NoOfFullTimeEmployees is more meaningful than the literal constant 49.

  2. It’s easier to change a single symbolic constant declaration than to find and replace all occurrences of a literal in a program.

However, using symbolic constants instead of literals can be taken too far. It is not necessary to replace all literals with constants. There are some constants that are intuitively obvious to everyone and that are not going to change; for example, the number of days in a week or months in a year. These values can be left as literals without reducing the readability or maintainability of the code.

 

Enumerations

 

In situations where a variable can only take on a specific set of values, such as colors or genders, enumerations allow you to create new types and to declare variables whose values are restricted to the enumerated set. Enumerations are declared by the keyword enum, followed by the type name, an opening brace ({), the enumerated values separated by commas, a closing brace (}), and a semicolon (;). Variables are then declared as an enumerated type, and they can only receive one of the enumerated values:

 

 

 

 

 

 

 

enum WorkDays { Monday, Tuesday, Wednesday, Thursday, Friday };

const int Saturday = 7;

WorkDays WorkingDay;

WorkingDay = Thursday;   // Thursday is a member of the WorkDays

                         // enumerated type and therefore can be

                         // assigned to the WorkingDay variable.

WorkingDay = Saturday;   // Although Saturday is an integer

                         // constant, it is not part of the

                         // enumerated type WorkingDay and

                         // therefore can’t be assigned to the

                         // WorkingDay variable.

 

Typedefs

 

A typedef is a user-defined synonym for an existing type. To create a synonym for a type, you use the keyword typedef followed by the name of the type and the new name you are defining. Because typedef is a C++ statement, you also need a closing semicolon:

typedef unsigned int positiveNumber;

This typedef declares positiveNumber to be a synonym of unsigned int and can be used in a declaration instead of the actual type name:

positiveNumber one, two;

 

Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7 | Part 8 | Part 9 | Part 10

 


 

< .Net Type, Variable & Operator 1 | Main | .Net Type, Variable & Operator 3 >