5.4 Initializing Variables

I l @ ve RuBoard

5.4 Initializing Variables

C++ allows variables to be initialized in the declaration statement. For example, the following statement declares the integer counter and initializes it to 0.

 int counter(0);    // number cases counted so far 

The older C-style syntax is also supported:

 int counter = 0;    // number cases counted so far 

Arrays can be initialized in a similar manner. The element list must be enclosed in curly braces ({}). For example:

 // Product numbers for the parts we are making int product_codes[3] = {10, 972, 45}; 

This is equivalent to:

 product_codes[0] = 10;  product_codes[1] = 972;  product_codes[2] = 45; 

The number of elements in the curly braces ({}) does not have to match the array size . If too many numbers are present, a warning will be issued. If there are not enough numbers, the extra elements will be initialized to 0.

If no dimension is given, C++ will determine the dimension from the number of elements in the initialization list. For example, we could have initialized our variable product_codes with the statement:

 // Product numbers for the parts we are making int product_codes[] = {10, 972, 45}; 

5.4.1 Bounds Errors

In Example 5-2 the data array has five elements. So what happens if we accidently use an illegal index? For example:

 int data[5]; // ... result = data[99];   // Bad 

The results are undefined. Most of the time you'll get a random number. Other times, your program may abort with an error. Things get worse if you use the bad index on the left side of an assignment:

 int data[5]; // ... data[99] = 55;   // Very bad 

In this case, if you're lucky, the program will abort. If you're not so lucky, the program will change a random memory location. This location could hold another variable, vital system data, or something else important. The result is that your program fails in a strange and hard to debug manner.

Therefore it is extremely important to make sure that any time you use an array index that it's within bounds. Example 5-6 illustrates a program that contains an array bounds error.

Example 5-6. bounds/bound_err.cpp
 #include <iostream> const int N_PRIMES = 7; // Number of primes // The first few prime numbers int primes[N_PRIMES] = {2, 3, 5, 7, 11, 13, 17}; int main(  ) {     int index = 10;     std::cout << "The tenth prime is " << primes[index] << '\n';     return (0); } 

When this program executes on some machines it outputs:

 Segmentation violation Core dumped 

On others it just gives us funny information:

 The tenth prime is 0 

Bounds errors are ugly, nasty things that should be stamped out whenever possible. One solution to this problem is to use the assert statement. The assert statement tells C++, "This can never happen, but if it does, abort the program in a nice way." One thing you find out as you gain programming experience is that things that can "never happen" happen with alarming frequency. So just to make sure that things work as they are supposed to, it's a good idea to put lots of self checks in your program.

The assert statement is one form of self check. When we add it to Example 5-6 we get Example 5-7.

Example 5-7. bounds/bound_c1.cpp
 #include <iostream> #include <assert.h> const int N_PRIMES = 7; // Number of primes // The first few prime numbers int primes[N_PRIMES] = {2, 3, 5, 7, 11, 13, 17}; int main(  ) {     int index = 10;     assert(index < N_PRIMES);     assert(index >= 0);     std::cout << "The tenth prime is " << primes[index] << '\n';     return (0); } 

The statement:

 #include <assert.h> 

tells C++ that we want to use the assert module. Now we know that the index must be in range. After all, our program could never contain an error that might generate a bad index. But just to make sure, we check to see if it's in range using the statement:

 assert(index < N_PRIMES); assert(index >= 0); 

Now when the program hits the assert statement, the assertion fails and an error message is issued:

 bound_c1: bound_c1.cpp:11: int main(  ): Assertion `index < 7' failed. Abort (core dumped) 

The program then aborts. Aborting is a nasty way of handling an error, but it's better than doing nothing at all. (This is not true in every case; see sidebar.)

A Real System Crash

On June 4, 1996, a computer program was started. After 30 seconds, an assert statement failed and the system shut down. While shutting down is the safest thing to do in most circumstances, it was the wrong thing to do in this one.

That's because the computer was on top of an Ariane 5 rocket, and its job was to keep the rocket pointed in the right direction.

The result was quite literally a system crash. (The rocket had to be blown up before it dove into the ground.)

It should be noted that in 99.99% of the cases, aborting the program is the right thing to do. There are very few programs like the guidance software for the Ariane 5 that must keep running no matter what.

There is a problem with our code. The programmer must remember that the array data has a limit of N_PRIMES . This means that he has to count and to keep track of two things: the number of items in data and the value of N_PRIMES . It would be better to do things automatically.

The C++ operation sizeof returns the size of a variable in bytes. So sizeof(data) is 28 (7 elements of 4 bytes each). This assumes that integers are 4 bytes long. (This is system-dependent.)

But we want the number of elements in data , not the number of bytes. The size of the first element is sizeof(data[0]) , and since each element is the same size, this is the size of every element. So we have the total number of bytes in the array and the number of bytes in an element. From this we can compute the number of elements in the array:

 sizeof(data) / sizeof(data[0]) 

Now we can rewrite the code and eliminate the need to count elements. The results are in Example 5-8.

Example 5-8. bounds/bound_c2.cpp
 #include <iostream> #include <assert.h> // The first few prime numbers int primes[] = {2, 3, 5, 7, 11, 13, 17}; int main(  ) {     int index = 10;     assert(index < (sizeof(primes)/sizeof(primes[0])));     assert(index >= 0);     std::cout << "The tenth prime is " << primes[index] << '\n';     return (0); } 
I l @ ve RuBoard


Practical C++ Programming
Practical C Programming, 3rd Edition
ISBN: 1565923065
EAN: 2147483647
Year: 2003
Pages: 364

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net