⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter 5 expressions -- valvano.htm

📁 介绍了在嵌入式系统中如何用c来设计嵌入式软件
💻 HTM
📖 第 1 页 / 共 4 页
字号:
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>&nbsp;&nbsp;&nbsp;&nbsp;a=b=0;&nbsp;/* 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>&nbsp;&nbsp;&nbsp;&nbsp;a+=b;&nbsp;&nbsp;/* same as a=a+b 
*/ <BR>&nbsp;&nbsp;&nbsp;&nbsp;a-=b;&nbsp;&nbsp;/* same as a=a-b */ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;a*=b;&nbsp;&nbsp;/* same as a=a*b */ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;a/=b;&nbsp;&nbsp;/* same as a=a/b */ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;a%=b;&nbsp;&nbsp;/* same as a=a%b */ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;a&lt;&lt;=b;&nbsp;/* same as a=a&lt;&lt;b */ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;a&lt;&lt;=b;&nbsp;/* same as a=a&lt;&lt;b */ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;a&gt;&gt;=b;&nbsp;/* same as a=a&gt;&gt;b */ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;a|=b;&nbsp;&nbsp;/* same as a=a|b */ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;a&amp;=b;&nbsp;&nbsp;/* same as a=a&amp;b */ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;a^=b;&nbsp;&nbsp;/* 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>&nbsp;&nbsp;&nbsp;&nbsp;PORTA|=0x01;&nbsp;&nbsp;/* set PA0 high */ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;PORTB&amp;=~0x80;&nbsp;/* clear PB7 low */ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;PORTC^=0x40;&nbsp;&nbsp;/* 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>&nbsp;&nbsp;</CODE><FONT face="Times New Roman,Times">automatic 
conversion, <BR></FONT><CODE>&nbsp;&nbsp;</CODE><FONT 
face="Times New Roman,Times">implicit conversion, 
<BR></FONT><CODE>&nbsp;&nbsp;</CODE><FONT face="Times New Roman,Times">coercion, 
<BR></FONT><CODE>&nbsp;&nbsp;</CODE><FONT 
face="Times New Roman,Times">promotion, or 
<BR></FONT><CODE>&nbsp;&nbsp;</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%">&nbsp;</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>&nbsp;&nbsp;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])&gt;&gt;7;}</CODE></P>
<P><I>Listing 5-7: We can use a cast to force higher precision 
arithmetic</I></P>
<P>&nbsp;</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>&nbsp;</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 + -