📄 ch02.htm
字号:
<tt>8: cout << "The size of a char is:\t\t";</tt><tt>8a: cout << sizeof(char) << " bytes.\n";</tt><tt>9: cout << "The size of a float is:\t\t";</tt><tt>9a: cout << sizeof(float) << " bytes.\n";</tt><tt>10: cout << "The size of a double is:\t";</tt><tt>10a: cout << sizeof(double) << " bytes.\n";</tt><tt>11: cout << "The size of a bool is:\t";</tt><tt>11a: cout << sizeof(bool) << " bytes.\n";</tt><tt>12: return 0;</tt><tt>13: }</tt><tt>The size of an int is: 4 bytes.</tt><tt>The size of a short int is: 2 bytes.</tt><tt>The size of a long int is: 4 bytes.</tt><tt>The size of a char is: 1 bytes.</tt><tt>The size of a float is: 4 bytes.</tt><tt>The size of a double is: 8 bytes.</tt><tt>The size of a bool is: 1 bytes.</tt></pre><blockquote> <hr> <p><strong>NOTE: </strong> On your computer, the number of bytes presented might be different. If the number of bytes reported for an <tt>int</tt> (the first line of output) is 2 bytes, you are using an older (and probably obsolete) 16-bit compiler. </p> <hr></blockquote><blockquote> <hr> <p><strong>TIP: </strong> If you are using Visual C++, you can run your program with <b>Ctrl+F5</b>. Your ouput displays, followed by</p> <p> <tt>Press any key to continue</tt></p> <p> This gives you time to look at the output; then, when you press a key, the window closes.</p> <p> If your compiler does not provide this service, you might find that the text scrolls by very quickly, and then you are returned to your IDE.</p> <p> In this case, add the following line to the top of the file:</p> <p> <tt>#include <conio.h></tt></p> <p> Add the following line just before <tt>return 0;</tt>:</p> <p> <tt> _getch();</tt></p> <p> This causes your program to pause after all the output is completed; it waits for you to press the spacebar or other character key. Add these lines to every sample program.</p> <hr></blockquote><p>Most of Listing 2.3 is probably pretty familiar to you. The one new feature is the use of the <tt>sizeof()</tt> operator, which is provided by your compiler and tells you the size of the object you pass as a parameter. For example, on line 5, the keyword <tt>int</tt> is passed into <tt>sizeof()</tt>. Using <tt>sizeof()</tt>, I determined that on my computer an <tt>int</tt> is equal to a long <tt>int</tt>, which is 4 bytes. </p><p><b>Using an Integer Variable</b></p><p>In Decryptix!, we want to keep track of how many different letters the code can contain. Because this is a number (between <tt>1</tt> and <tt>26</tt>), you can keep track of this value with an <tt>int</tt>. In fact, because this number is very small, it can be a short <tt>int</tt>, and because it must be a positive number, in can be an unsigned short <tt>int</tt>.</p><p>Using a short <tt>int</tt> might save me two bytes. There was a time when such a savings was significant; today, however, I rarely bother. Short <tt>int</tt>s can be written just as short, so it is the height of profligacy to waste bytes because I'm too lazy to write short rather than <tt>int</tt>.</p><p>When I was a boy, bytes were worth something, and I watched every one. Today, for most applications, bytes are cheap. They are the pennies of programming, and these days most programmers just keep a small cup of bytes out on the counter and let customers take them when they need a few, occasionally tossing extra bytes into the cup for the next person to use. </p><blockquote> <hr> <p><strong>NOTE: </strong> In the 1960s, many programmers worked in primitive languages, which represented dates as characters. Each number in the date consumed one byte (so 1999 consumed 4 bytes). Obsessive concern about saving a byte here and a byte there led many programmers to shorten dates from four digits (1999) to two (99), thus saving two bytes and creating the Y2K problem. </p> <hr></blockquote><p>For the vast majority of programs, the only built-in types to be concerned with are <tt>int</tt>, <tt>char</tt>, and <tt>bool</tt>. Now and again you'll use unsigned <tt>int</tt>s, <tt>float</tt>s, and <tt>double</tt>s. Of course, most of the time you'll use your own programmer-created types. </p><p>Signed and Unsigned</p><p>After you determine the size of an integer, you're not quite done. An integer (and a short and a long) can be <i>signed</i> or <i>unsigned</i>. If it is signed, it can store negative and positive numbers. If it is unsigned, it can store only positive numbers.</p><p>Because signed numbers can store negative as well as positive numbers, the absolute value they can store is only half as large.</p><p>Wrapping Around an Unsigned Integer</p><p>The fact that unsigned long integers have a limit to the values they can hold is only rarely a problem--but what happens if you <i>do</i> run out of room?</p><p>When an unsigned integer reaches its maximum value, it wraps around and starts over, much like a car odometer. Listing 2.4 shows what happens if you try to put too large a value into a short integer.</p><p><b>Listing 2.4 Wrapping Around an Unsigned Integer</b></p><pre><tt>1: #include <iostream></tt><tt>2: using namespace std;</tt><tt>3: int main()</tt><tt>4: {</tt><tt>5: unsigned short int smallNumber;</tt><tt>6: smallNumber = 65535;</tt><tt>7: cout << "small number:" << smallNumber << endl;</tt><tt>8: smallNumber++;</tt><tt>9: cout << "small number:" << smallNumber << endl;</tt><tt>10: smallNumber++;</tt><tt>11: cout << "small number:" << smallNumber << endl;</tt><tt>12: return 0;</tt><tt>13: }</tt><tt>small number:65535</tt><tt>small number:0</tt><tt>small number:1</tt></pre><p>On line 4, <tt>smallNumber</tt> is declared to be an unsigned short <tt>int</tt>, which on my computer is a two-byte variable that can hold a value between <tt>0</tt> and <tt>65,535</tt>. On line 5, the maximum value is assigned to <tt>smallNumber</tt>, and it is printed on line 6 using the standard output library function. Note that because we did not add the line <tt>using namespace std;</tt> we must explicitly identify <tt>cout</tt>. The keyword endl is also part of the standard library and must be explicitly identified.</p><p>On line 7, <tt>smallNumber</tt> is <i>incremented</i>; that is, one is added to it. The symbol for incrementing is <tt>++</tt> (as in the name <i>C++</i>, an incremental increase from C). Thus, the value in <tt>smallNumber</tt> is <tt>65,536</tt>. However, unsigned short integers can't hold a number larger than <tt>65,535</tt>, so the value is wrapped around to <tt>0</tt>, which is printed on line 8.</p><blockquote> <hr> <p> <b>Incremented</b>--When a value is incremented, it is increased by one.</p> <hr></blockquote><p>On line 9, <tt>smallNumber</tt> is incremented again, and then its new value, <tt>1</tt>, is printed.</p><h4>Wrapping Around a Signed Integer</h4><p>A signed integer is different from an unsigned integer in that half of the values you can represent are negative. Instead of picturing a traditional car odometer, you might picture one that rotates up for positive numbers and down for negative numbers. One mile from <tt>0</tt> is either <tt>1</tt> or <tt>-1</tt>. When you run out of positive numbers, you run right into the largest negative numbers and then count back down to <tt>0</tt>. Listing 2.5 shows what happens when you add <tt>1</tt> to the maximum positive number in short integer.</p><p><b>Listing 2.5 Wrapping Around a Signed Integer</b></p><pre><tt>1: #include <iostream></tt><tt>2: using namespace std;</tt><tt>3: int main()</tt><tt>4: {</tt><tt>5: short int smallNumber;</tt><tt>6: smallNumber = 32767;</tt><tt>7: cout << "small number:" << smallNumber << endl;</tt><tt>8: smallNumber++;</tt><tt>9: cout << "small number:" << smallNumber << endl;</tt><tt>10: smallNumber++;</tt><tt>11: cout << "small number:" << smallNumber << endl;</tt><tt>12: return 0;</tt><tt>13: }</tt><tt>small number:32767</tt><tt>small number:-32768</tt><tt>small number:-32767</tt></pre><p>On line 4, <tt>smallNumber</tt> is declared to be a signed short integer. (If you don't explicitly say that it is unsigned, it is assumed that it is signed.) The program proceeds much as the preceding program does, but the output is quite different. </p><p>The bottom line is that just like an unsigned integer, the signed integer wraps around from its highest positive value to its highest negative value.</p><h3> <a name="Heading10">Constants</a></h3><p>The point of a variable is to store a value. I call it a variable because it might vary: That is, the value might change over the course of the program. <tt>howManyLetters</tt> starts out as <tt>0</tt>, but is assigned a new value based on the user's input.</p><p>At times, however, you need a fixed value--one that won't change over the course of the program. The minimum number of letters a user is allowed to choose is an example of a fixed value; the programmer determines it long before the program runs.</p><p>A fixed value is called a <i>constant</i>. There are two flavors of constants: literal and symbolic. </p><h4>Literal Constants</h4><p>A <i>literal constant</i> is a value that is typed directly into your program wherever it is needed. For example</p><pre><tt>int howManyLetters = 7;</tt></pre><p><tt>howManyLetters</tt> is a variable of type <tt>int</tt>; <tt>7</tt> is a literal constant. You can't assign a value to <tt>7</tt>, and its value can't be changed. </p><h4>Symbolic Constants</h4><p>Like variables, <i>symbolic constants</i> are storage locations, but their contents never change during the course of your program. When you declare a constant, what you are really doing is saying to the compiler, "Treat this like a variable, but if I ever change the value stored here, let me know." The compiler then tells you with a compiler error.</p><p>You'll define <tt>minLetters</tt> to be a symbolic constant--specifically, a constant integer whose value is <tt>2</tt>. Note that the constant <tt>minLetters</tt> is used on a number of different lines of code. If you decide later to change the value to <tt>3</tt>, you need to change it only in one place--the change affects many lines of code. This helps you avoid bugs in your code. Changes are localized, so there is little chance of one line assuming that the minimum number of letters is two, whereas another line assumes that it is three.</p><p>There are actually two ways to declare a symbolic constant in C++. The old, traditional, and now obsolete way is with a preprocessor directive: <tt>#define</tt>. </p><h4>Defining Constants with <tt>#define</tt></h4><p>To define a constant in the traditional way, enter the following code:</p><pre><tt>#define minLetters 2</tt></pre><p>Note that when it is declared this way, <tt>minLetters</tt> is of no particular type (<tt>int</tt>, <tt>char</tt>, and so on). <tt>#define</tt> does a simple text substitution. Every time the preprocessor sees the word <tt>minLetters</tt>, it puts in the text <tt>2</tt>.</p><p>Because the preprocessor runs before the compiler, your compiler never sees your constant; it sees the number <tt>2</tt>. Later, when I discuss debugging, you'll find that <tt>#define</tt>d constants do not appear as symbolic constants in the debugger; you see only the literal value (<tt>2</tt>). </p><h4>Defining Constants with <tt>const</tt></h4><p>Although <tt>#define</tt> works, there is a newer, much better way to define constants in C++:</p><pre><tt> const int minLetters = 2;</tt></pre><p>This creates the symbolic constant <tt>minLetters</tt> but ensures that it has a particular type--<tt>integer</tt>. If you try to write</p><pre><tt> const int minLetters = 3.2;</tt></pre><p>the compiler complains that you have declared it to be an <tt>int</tt> but that you are trying to initialize it with a <tt>float</tt>.</p><p>The purpose of a debugger is to enable you to peek inside the machine and watch your variables change as the program runs. You can accomplish a lot with a debugger, and aside from your text editor, it is your most important tool.</p><p>Unfortunately, most novices don't become comfortable with their debugger until very late in their experience of C++. This is a shame because the debugger is a terrific learning tool.</p><p>Although every debugger is different and you definitely want to consult your documentation, this excursion illustrates how you might debug Listing 2.1 using the Microsoft Visual C++ 6.0 Enterprise Edition debugger. Your exact experience might vary, but the principles are the same.</p><p>Follow these steps:</p><p><dl> <dt> <dd> <p><b>1.</b> Create a project called Decryptix.</p> <dt> <dd> <p><b>2.</b> Open a new file called decryptix.cpp.</p> <dt> <dd> <p><b>3.</b> Enter the program as it is written or download it from my Web site.</p> <dt> <dd> <p><b>4.</b> Place the cursor on the first line after the opening brace and press <b>F9</b>. You see a red dot in the margin next to that line, indicating a break point (see Figure 2.4). </dl><p></p><p><b>Figure 2.4 </b><i>A break point showing in Visual C++.</i></p><p> <dl> <dt> <dd> <p><b>5.</b> Press <b>Go</b> (<b>F5</b>). The debugger starts, and your code runs.</p> <dt> <dd> <p><b>6.</b> Choose <b>View/Debug Windows</b> and make sure that the Watch and Variables windows are open (see Figure 2.5). </dl><p></p><p><b>Figure 2.5 </b><i>Checking that the Watch and Variables windows are open.</i></p><p> <dl> <dt> <dd> <p><b>7.</b> Press <b>Step Over</b> (<b>F10</b>) to walk through the code line by line.</p> <dt> <dd> <p><b>8.</b> Scroll down to the line on which <tt>duplicatesAllowed</tt> is defined, and place a break point there. Press <b>Go </b>(<b>F5</b>) to run until this second break point.</p> <dt> <dd> <p><b>9.</b> Note in the variables window that <tt>howManyLetters</tt> and <tt>howManyPositions</tt> are zero, but that <tt>duplicatesAllowed</tt> has a random value (see Figure 2.6). </dl><p></p><p><b>Figure 2.6 </b><i>Looking at values in the debugger.</i></p><p><dl> <dt> <dd> <p><b>10.</b> Press <b>Step Over</b> (<b>F10</b>) to step over this one line of code. This causes <tt>duplicatesAllowed</tt> to be created and initialized. Note that the value that is shown in the variables window is now correct (<tt>false</tt> is indicated as <tt>0</tt>, and <tt>true</tt> is indicated as <tt>1</tt>). Note also that <tt>round</tt> has a random value. Press <b>F10</b> again; <tt>round</tt> is initialized to <tt>1</tt>.</p> <dt> <dd> <p><b>11.</b> Explore the debugger and read through the documentation and help files. The more time you spend in the debugger, the more you will come to appreciate its tremendous value, both for finding bugs and for helping you understand how programs work. </dl><p></p><p> </p><CENTER><P><HR> <A HREF="../index.htm"><IMG SRC="../button/contents.gif" WIDTH="128"HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A> <BR> <BR><p></P><P>© <A HREF="../copy.htm">Copyright 1999</A>, Macmillan Computer Publishing. Allrights reserved.</p></CENTER></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -