📄 chapter2.html
字号:
<h2><a name="s2.4">2.4 Declarations</a></h2>All variables must be declared before use, although certain declarationscan be made implicitly by content. A declaration specifies a type, andcontains a list of one or more variables of that type, as in<pre> int lower, upper, step; char c, line[1000];</pre>Variables can be distributed among declarations in any fashion; the listsabove could well be written as<pre> int lower; int upper; int step; char c; char line[1000];</pre>The latter form takes more space, but is convenient for adding a comment toeach declaration for subsequent modifications.<p>A variable may also be initialized in its declaration. If the name isfollowed by an equals sign and an expression, the expression serves as aninitializer, as in<pre> char esc = '\\'; int i = 0; int limit = MAXLINE+1; float eps = 1.0e-5;</pre>If the variable in question is not automatic, the initialization is doneonce only, conceptionally before the program starts executing, and theinitializer must be a constant expression. An explicitly initializedautomatic variable is initialized each time the function or block it is in isentered; the initializer may be any expression. External and static variablesare initialized to zero by default. Automatic variables for which is noexplicit initializer have undefined (i.e., garbage) values.<p>The qualifier <tt>const</tt> can be applied to the declaration of any variableto specify that its value will not be changed. For an array, the <tt>const</tt>qualifier says that the elements will not be altered.<pre> const double e = 2.71828182845905; const char msg[] = "warning: ";</pre>The <tt>const</tt> declaration can also be used with array arguments, toindicate that the function does not change that array:<pre> int strlen(const char[]);</pre>The result is implementation-defined if an attempt is made to change a<tt>const</tt>.<h2><a name="s2.5">2.5 Arithmetic Operators</a></h2>The binary arithmetic operators are <tt>+</tt>, <tt>-</tt>, <tt>*</tt>,<tt>/</tt>, and the modulus operator <tt>%</tt>. Integer division truncatesany fractional part. The expression<pre> x % y</pre>produces the remainder when <tt>x</tt> is divided by <tt>y</tt>, and thus iszero when <tt>y</tt> divides <tt>x</tt> exactly. For example, a year is a leapyear if it is divisible by 4 but not by 100, except that years divisible by 400<em>are</em> leap years. Therefore<pre> if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) printf("%d is a leap year\n", year); else printf("%d is not a leap year\n", year);</pre>The <tt>%</tt> operator cannot be applied to a <tt>float</tt> or <tt>double</tt>.The direction of truncation for <tt>/</tt> and the sign of the result for <tt>%</tt>are machine-dependent for negative operands, as is the action taken onoverflow or underflow.<p>The binary <tt>+</tt> and <tt>-</tt> operators have the same precedence, whichis lower than the precedence of <tt>*</tt>, <tt>/</tt> and <tt>%</tt>, which isin turn lower than unary <tt>+</tt> and <tt>-</tt>. Arithmetic operatorsassociate left to right.<p>Table 2.1 at the end of this chapter summarizes precedenceand associativity for all operators.<h2><a name="s2.6">2.6 Relational and Logical Operators</a></h2>The relational operators are<pre> > >= < <=</pre>They all have the same precedence. Just below them in precedence are theequality operators:<pre> == !=</pre>Relational operators have lower precedence than arithmetic operators, so anexpression like <tt>i < lim-1</tt> is taken as <tt>i < (lim-1)</tt>, aswould be expected.<p>More interesting are the logical operators <tt>&&</tt> and <tt>||</tt>.Expressions connected by <tt>&&</tt> or <tt>||</tt> are evaluatedleft to right, and evaluation stops as soon as the truth or falsehood of theresult is known. Most C programs rely on these properties. For example, hereis a loop from the input function <tt>getline</tt> that we wrote in<a href="chapter1.html">Chapter 1</a>:<pre> for (i=0; i < lim-1 && (c=getchar()) != '\n' && c != EOF; ++i) s[i] = c;</pre>Before reading a new character it is necessary to check that there is room tostore it in the array <tt>s</tt>, so the test <tt>i < lim-1</tt><em>must</em> be made first. Moreover, if this test fails, we must not go onand read another character.<p>Similarly, it would be unfortunate if <tt>c</tt> were tested against<tt>EOF</tt> before <tt>getchar</tt> is called; therefore the call andassignment must occur before the character in <tt>c</tt> is tested.<p>The precedence of <tt>&&</tt> is higher than that of <tt>||</tt>, andboth are lower than relational and equality operators, so expressions like<pre> i < lim-1 && (c=getchar()) != '\n' && c != EOF</pre>need no extra parentheses. But since the precedence of <tt>!=</tt> is higherthan assignment, parentheses are needed in<pre> (c=getchar()) != '\n'</pre>to achieve the desired result of assignment to <tt>c</tt> and then comparisonwith <tt>'\n'</tt>.<p>By definition, the numeric value of a relational or logical expression is 1if the relation is true, and 0 if the relation is false.<p>The unary negation operator <tt>!</tt> converts a non-zero operand into 0, anda zero operand in 1. A common use of <tt>!</tt> is in constructions like<pre> if (!valid)</pre>rather than<pre> if (valid == 0)</pre>It's hard to generalize about which form is better. Constructions like<tt>!valid</tt> read nicely (``if not valid''), but more complicated ones canbe hard to understand.<p><strong>Exercise 2-2.</strong> Write a loop equivalent to the <tt>for</tt>loop above without using <tt>&&</tt> or <tt>||</tt>.<h2><a name="s2.7">2.7 Type Conversions</a></h2>When an operator has operands of different types, they are converted to acommon type according to a small number of rules. In general, the onlyautomatic conversions are those that convert a ``narrower'' operand into a``wider'' one without losing information, such as converting an integer intofloating point in an expression like <tt>f + i</tt>. Expressions that don't makesense, like using a <tt>float</tt> as a subscript, are disallowed. Expressionsthat might lose information, like assigning a longer integer type to ashorter, or a floating-point type to an integer, may draw a warning, but theyare not illegal.<p>A <tt>char</tt> is just a small integer, so <tt>char</tt>s may be freely usedin arithmetic expressions. This permits considerable flexibility in certainkinds of character transformations. One is exemplified by this naiveimplementation of the function <tt>atoi</tt>, which converts a string of digitsinto its numeric equivalent.<pre> /* atoi: convert s to integer */ int atoi(char s[]) { int i, n; n = 0; for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i) n = 10 * n + (s[i] - '0'); return n; }</pre>As we discussed in <a href="chapter1.html">Chapter 1</a>, the expression<pre> s[i] - '0'</pre>gives the numeric value of the character stored in <tt>s[i]</tt>, because thevalues of <tt>'0'</tt>, <tt>'1'</tt>, etc., form a contiguous increasingsequence.<p>Another example of <tt>char</tt> to <tt>int</tt> conversion is the function<tt>lower</tt>, which maps a single character to lower case <em>for the ASCIIcharacter set</em>. If the character is not an upper case letter,<tt>lower</tt> returns it unchanged.<pre> /* lower: convert c to lower case; ASCII only */ int lower(int c) { if (c >= 'A' && c <= 'Z') return c + 'a' - 'A'; else return c; }</pre>This works for ASCII because corresponding upper case and lower case lettersare a fixed distance apart as numeric values and each alphabet is contiguous-- there is nothing but letters between <tt>A</tt> and <tt>Z</tt>. This latterobservation is not true of the EBCDIC character set, however, so this codewould convert more than just letters in EBCDIC.<p>The standard header <tt><ctype.h></tt>, described in <ahref="appb.html">Appendix B</a>, defines a family of functions that providetests and conversions that are independent of character set. For example, thefunction <tt>tolower</tt> is a portable replacement for the function<tt>lower</tt> shown above. Similarly, the test<pre> c >= '0' && c <= '9'</pre>can be replaced by<pre> isdigit(c)</pre>We will use the <tt><ctype.h></tt> functions from now on.<p>There is one subtle point about the conversion of characters to integers. Thelanguage does not specify whether variables of type <tt>char</tt> are signedor unsigned quantities. When a <tt>char</tt> is converted to an <tt>int</tt>,can it ever produce a negative integer? The answer varies from machine tomachine, reflecting differences in architecture. On some machines a<tt>char</tt> whose leftmost bit is 1 will be converted to a negative integer(``sign extension''). On others, a <tt>char</tt> is promoted to an int byadding zeros at the left end, and thus is always positive.<p>The definition of C guarantees that any character in the machine's standardprinting character set will never be negative, so these characters willalways be positive quantities in expressions. But arbitrary bit patternsstored in character variables may appear to be negative on some machines, yetpositive on others. For portability, specify <tt>signed</tt> or <tt>unsigned</tt>if non-character data is to be stored in <tt>char</tt> variables.<p>Relational expressions like <tt>i > j</tt> and logical expressionsconnected by <tt>&&</tt> and <tt>||</tt> are defined to have value 1if true, and 0 if false. Thus the assignment<pre> d = c >= '0' && c <= '9'</pre>sets <tt>d</tt> to 1 if <tt>c</tt> is a digit, and 0 if not. However, functions like<tt>isdigit</tt> may return any non-zero value for true. In the test part of<tt>if</tt>, <tt>while</tt>, <tt>for</tt>, etc., ``true'' just means ``non-zero'',so this makes no difference.<p>Implicit arithmetic conversions work much as expected. In general, if anoperator like <tt>+</tt> or <tt>*</tt> that takes two operands (a binary operator)has operands of different types, the ``lower'' type is <em>promoted</em> to the``higher'' type before the operation proceeds. The result is of the integertype. <a href="appa.html#sa.6">Section 6 of <a href="appa.html">Appendix A</a>states the conversion rules precisely. If there are no <tt>unsigned</tt>operands, however, the following informal set of rules will suffice:<ul><li>If either operand is <tt>long double</tt>, convert the other to <tt>long double</tt>.<li>Otherwise, if either operand is <tt>double</tt>, convert the other to <tt>double</tt>.<li>Otherwise, if either operand is <tt>float</tt>, convert the other to <tt>float</tt>.<li>Otherwise, convert <tt>char</tt> and <tt>short</tt> to <tt>int</tt>.<li>Then, if either operand is <tt>long</tt>, convert the other to <tt>long</tt>.</ul>Notice that <tt>float</tt>s in an expression are not automatically converted to<tt>double</tt>; this is a change from the original definition. In general,mathematical functions like those in <tt><math.h></tt> will use double precision.The main reason for using <tt>float</tt> is to save storage in large arrays, or,less often, to save time on machines where double-precision arithmetic isparticularly expensive.<p>Conversion rules are more complicated when <tt>unsigned</tt> operands areinvolved. The problem is that comparisons between signed and unsigned valuesare machine-dependent, because they depend on the sizes of the various integertypes. For example, suppose that <tt>int</tt> is 16 bits and <tt>long</tt> is 32bits. Then <tt>-1L < 1U</tt>, because <tt>1U</tt>, which is an <tt>unsigned int</tt>, ispromoted to a <tt>signed long</tt>. But <tt>-1L > 1UL</tt> because <tt>-1L</tt>is promoted to <tt>unsigned long</tt> and thus appears to be a large positive
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -