📄 chapter 5 expressions -- valvano.htm
字号:
Operators</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">The assignment operator is used to store
data into variables. The syntax is </FONT><CODE>variable=expression;</CODE><FONT
face="Times New Roman,Times"> where </FONT><CODE>variable</CODE><FONT
face="Times New Roman,Times"> has been previously defined. At run time, the
result of the expression is saved into the variable. If the type of the
expression is different from the variable, then the result is automatically
converted. For more information about types and conversion, see </FONT><A
href="http://www.ece.utexas.edu/~valvano/embed/chap5/chap5.htm#CASTS">expression
type and explicit cast</A><A
href="http://www.ece.utexas.edu/~valvano/embed/chap5/chap5.htm#ASSIGNMENT">ing</A><FONT
face="Times New Roman,Times">. The assignment operation itself has a result, so
the assignment operation can be nested</FONT>.<BR><CODE>int a,b;</CODE><FONT
face="Courier,Courier New" color=#008000 size=2><BR></FONT><CODE>void
initialize(void){ <BR> a=b=0; /* set both variables
to zero */ <BR>}</CODE></P>
<P><I>Listing 5-3: Example of a nested assignment operation</I></P>
<P><FONT face="Times New Roman,Times">The read/modify write assignment operators
are convenient. Examples are shown below. </FONT><BR><CODE>int a,b;</CODE><FONT
face="Courier,Courier New" color=#008000 size=2><BR></FONT><CODE>void
initialize(void){ <BR> a+=b; /* same as a=a+b
*/ <BR> a-=b; /* same as a=a-b */
<BR> a*=b; /* same as a=a*b */
<BR> a/=b; /* same as a=a/b */
<BR> a%=b; /* same as a=a%b */
<BR> a<<=b; /* same as a=a<<b */
<BR> a<<=b; /* same as a=a<<b */
<BR> a>>=b; /* same as a=a>>b */
<BR> a|=b; /* same as a=a|b */
<BR> a&=b; /* same as a=a&b */
<BR> a^=b; /* same as a=a^b */
<BR>}</CODE></P>
<P><I>Listing 5-4 List of all read/modify/write assignment operations</I></P>
<P><FONT face="Times New Roman,Times">Most compilers will produce the same code
for the short and long version of the operation. Therefore you should use the
read/modify/write operations only in situations that make the software easier to
understand. </FONT><FONT face="Courier,Courier New" color=#008000
size=2><BR></FONT><CODE>void function(void){
<BR> PORTA|=0x01; /* set PA0 high */
<BR> PORTB&=~0x80; /* clear PB7 low */
<BR> PORTC^=0x40; /* toggle PC6 */
<BR>}</CODE></P>
<P><I>Listing 5-5 Good examples of read/modify/write assignment
operations</I></P>
<P><I><B><FONT face=Helvetica,Arial><A name=CASTS></A>Expression Types and
Explicit Casting</FONT></B></I></P>
<P><FONT face="Times New Roman,Times">We saw earlier that numbers are
represented in the computer using a wide range of formats. A list of these
formats is given in Table 5.7. Notice that for the 6811 and 6812, the <B>int</B>
and <B>short</B> types are the same. On the other hand with the Intel Pentium,
the <B>int</B> and <B>long</B> types are the same. This difference may cause
confusion, when porting code from one system to another. I suggest you use the
<B>int</B> type when you are interested in efficiency and don't care about
precision, and use the <B>short</B> type when you want a variable with a 16-bit
precision.</FONT></P>
<P>
<TABLE cellSpacing=0 border=0>
<TBODY>
<TR>
<TD vAlign=top width="25%"><U><FONT size=2>type</FONT></U></TD>
<TD vAlign=top width="25%"><U><FONT size=2>range</FONT></U></TD>
<TD vAlign=top width="25%"><U><FONT size=2>precision </FONT></U></TD>
<TD vAlign=center width="25%"><U><FONT size=2>example
variable</FONT></U><FONT size=2> </FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>unsigned char</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>0 to 255</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>8 bits</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>unsigned char uc;</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>char</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>-127 to 127</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>8 bits</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>char sc;</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>unsigned int</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>0 to 65535U</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>16 bits</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>unsigned int ui;</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>int</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>-32767 to 32767</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>16 bits</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>int si;</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>unsigned short </FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>0 to 65535U</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>16 bits</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>unsigned short us;
</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>short</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>-32767 to 32767</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>16 bits</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>short ss;</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>long</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>-2147483647L to 2147483647L
</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>32 bits</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>long
sl;</FONT></TD></TR></TBODY></TABLE></P>
<ADDRESS>Table 5-7. Available number formats for the ICC11/ICC12/Hiware
compilers</ADDRESS>
<P><FONT face="Times New Roman,Times">An obvious question arises, what happens
when two numbers of different types are operated on? Before operation, the C
compiler will first convert one or both numbers so they have the same type. The
conversion of one type into another has many names:
<BR></FONT><CODE> </CODE><FONT face="Times New Roman,Times">automatic
conversion, <BR></FONT><CODE> </CODE><FONT
face="Times New Roman,Times">implicit conversion,
<BR></FONT><CODE> </CODE><FONT face="Times New Roman,Times">coercion,
<BR></FONT><CODE> </CODE><FONT
face="Times New Roman,Times">promotion, or
<BR></FONT><CODE> </CODE><FONT
face="Times New Roman,Times">widening.</FONT></P>
<P><FONT face="Times New Roman,Times">There are three ways to consider this
issue. The first way to think about this is if the range of one type completely
fits within the range of the other, then the number with the smaller range is
converted (promoted) to the type of the number with the larger range. In the
following examples, a number of type1 is added to a number of type2. In each
case, the number range of type1 fits into the range of type2, so the parameter
of type1 is first promoted to type2 before the addition. </FONT></P>
<P>
<TABLE cellSpacing=0 border=0>
<TBODY>
<TR>
<TD vAlign=top width="25%"><U><FONT size=2>type1</FONT></U></TD>
<TD vAlign=top width="25%"> </TD>
<TD vAlign=top width="25%"><U><FONT size=2>type2</FONT></U></TD>
<TD vAlign=center width="25%"><U><FONT size=2>example</FONT></U></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>unsigned char</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>fits inside </FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>unsigned short </FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>uc+us is of type unsigned
short</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>unsigned char</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>fits inside</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>short</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>uc+ss is of type
short</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>unsigned char</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>fits inside</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>long</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>uc+sl is of type
long</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>char</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>fits inside</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>short</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>sc+ss is of type
short</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>char</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>fits inside</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>long</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>sc+sl is of type
long</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>unsigned short </FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>fits inside</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>long</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>us+sl is of type
long</FONT></TD></TR>
<TR>
<TD vAlign=top width="25%"><FONT size=2>short</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>fits inside</FONT></TD>
<TD vAlign=top width="25%"><FONT size=2>long</FONT></TD>
<TD vAlign=center width="25%"><FONT size=2>ss+sl is of type
long</FONT></TD></TR></TBODY></TABLE></P>
<ADDRESS>Table 5-8. When the range of one type fits inside the range of another,
then conversion is simple</ADDRESS>
<P>The second way to consider mixed precision operations is that in most cases
the compiler will promote the number with the smaller precision into the other
type before operation. If the two numbers are of the same precision, then the
signed number is converted to unsigned. These automatic conversions may not
yield correct results. The third and best way to deal with mixed type operations
is to perform the conversions explicitly using the <B>cast</B> operation. We can
force the type of an expression by explicitly defining its type. This approach
allows the programmer to explicitly choose the type of the operation. Consider
the following digital filter with mixed type operations. In this example, we
explicitly convert x and y to signed 16 bit numbers and perform 16 bit signed
arithmetic. Note that the assignment of the result into y, will require a
demotion of the 16 bit signed number into 8 bit signed. Unfortunately, C does
not provide any simple mechanisms for error detection/correction (see <A
href="http://www.ece.utexas.edu/~valvano/embed/chap5/chap5.htm#OVERFLOW">overflow
and underflow</A>.)</P>
<P><CODE>char y; // output of the filter</CODE><FONT face="Courier,Courier New"
color=#008000 size=2><BR></FONT><CODE>unsigned char x; // input of the
filter<BR>void filter(void){ <BR> y = (12*(short)x +
56*(short)y)/100; <BR>}</CODE></P>
<P><I>Listing 5-6: Examples of the selection operator</I></P>
<P>We apply an explicit cast simply by preceeding the number or expression with
parentheses surrounding the type. In this next digital filter all numbers are of
the same type. Even so, we are worried that the intermediate result of the
mulitplications and additions might overflow the 16-bit arithmetic. We know from
digital signal processing that the final result will always fit into the 16-bit
variable. For more information on the design and analysis of digital filters,
see Chapter 15 of <U>Embedded Microcomputer Systems: Real Time Interfacing</U>
by Jonathan W. Valvano. In this example, the cast <CODE>(long)</CODE> will
specify the calculations be performed in 32-bit precision.</P>
<P><CODE>// y(n) = [113*x(n) + 113*x(n-2) - 98*y(n-2)]/128, channel specifies
the A/D channel<BR>short x[3],y[3]; // MACQs containing current and
previous<BR>#define OC5 0x20 <BR>#pragma interrupt_handler TOC5handler()<BR>void
TOC5handler(void){ <BR>TFLG1=OC5; // ack OC5F<BR>TC5=TC5+8333; //
fs=240Hz<BR>y[2]=y[1]; y[1]=y[0]; // shift MACQ<BR>x[2]=x[1]; x[1]=x[0];
<BR>x[0] = A2D(channel); // new
data<BR>y[0]=(113*((long)x[0]+(long)x[2])-98*(long)y[2])>>7;}</CODE></P>
<P><I>Listing 5-7: We can use a cast to force higher precision
arithmetic</I></P>
<P> </P>
<P>We saw in <A
href="http://www.ece.utexas.edu/~valvano/embed/chap1/chap1.htm">Chapter 1</A>,
casting was used to assign a symbolic name to an I/O port. In particular the
following define casts the number 0x0000 as a pointer type, which points to an
unsigned 8 bit data. More about pointers can be found in <A
href="http://www.ece.utexas.edu/~valvano/embed/chap7/chap7.htm">Chapter
7</A>.</P>
<P><CODE>#define PORTA *(unsigned char volatile *)(0x0000)</CODE></P>
<P> </P>
<P><B><I><FONT face=Helvetica,Arial><A name=SELECTION></A>Selection
operator</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">The selection operator takes three input
parameters and yields one output result. The format is</FONT></P>
<DIR>
<P><FONT face="Times New Roman,Times">Expr1 ? Expr2 : Expr3</FONT></P></DIR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -