• No results found

Chapter 3. C Language Features

3.6 Operators

HI-TECH C supports all the ANSI operators. The exact results of some of these are implementation defined. The following sections illustrate code produced by the compiler.

3.6.1

Integral Promotion

When there is more than one operand to an operator, they typically must be of exactly the same type. The compiler will automatically convert the operands, if necessary, so they have the same type. The conversion is to a “larger” type so there is no loss of information.

Even if the operands have the same type, in some situations they are converted to a different type before the operation. This conversion is called integral promotion. HI-TECH C performs these integral promotions where required. If you are not aware that the type has changed, the results of some expressions are not what would nor- mally be expected.

Integral promotion is the implicit conversion of enumerated types, signed or

unsigned varieties of char, short int or bit-field types to either signed int or

unsigned int. If the result of the conversion can be represented by an signed int, then that is the destination type, otherwise the conversion is to unsigned int. Consider the following example.

unsigned char count, a=0, b=50; if(a - b < 10)

count++;

The unsigned char result of a - b is 206 (which is not less than 10), but both a and

b are converted to signed int via integral promotion before the subtraction takes place. The result of the subtraction with these data types is -50 (which is less than 10) and hence the body of the if() statement is executed.

If the result of the subtraction is to be an unsigned quantity, then apply a cast. For example:

if((unsigned int)(a - b) < 10) count++;

The comparison is then done using unsigned int, in this case, and the body of the

if() would not be executed.

Another problem that frequently occurs is with the bitwise compliment operator, ~. This operator toggles each bit within a value. Consider the following code.

unsigned char count, c; c = 0x55;

if( ~c == 0xAA) count++;

If c contains the value 0x55, it often assumed that ~c will produce 0xAA, however the result is 0xFFAA and so the comparison in the above example would fail. The compiler may be able to issue a mismatched comparison error to this effect in some circum- stances. Again, a cast could be used to change this behavior.

Strictly speaking, this statement requires that the values of b and c should be promoted to unsigned int, the addition performed, the result of the addition cast to the type of

a, and then the assignment can take place. Even if the result of the unsigned int

addition of the promoted values of b and c was different to the result of the unsigned char addition of these values without promotion, after the unsigned int result was converted back to unsigned char, the final result would be the same. If an 8-bit addi- tion is more efficient than a 16-bit addition, the compiler will encode the former. If, in the above example, the type of a was unsigned int, then integral promotion would have to be performed to comply with the ANSI C standard.

3.6.2

Shifts applied to integral types

The ANSI standard states that the result of right shifting (>> operator) signed integral types is implementation defined when the operand is negative. Typically, the possible actions that can be taken are that when an object is shifted right by one bit, the bit value shifted into the Most Significant bit of the result can either be zero, or a copy of the Most Significant bit before the shift took place. The latter case amounts to a sign extension of the number.

HI-TECH C Compiler for PIC10/12/16 MCUs performs a sign extension of any signed

integral type (for example signed char, signed int or signed long). Thus an object with the signed int value 0x0124 shifted right one bit will yield the value 0x0092 and the value 0x8024 shifted right one bit will yield the value 0xC012. Right shifts of unsigned integral values always clear the Most Significant bit of the result.

Left shifts (<< operator), signed or unsigned, always clear the Least Significant bit of the result.

3.6.3

Rotation

The C language does not contain a rotate operator. It does allow shifts, as illustrated in

Section 3.6.2 “Shifts applied to integral types”. However the compiler will detect expressions that implement rotate operations using shift and logical operators. For the following code:

c = (c << 1) | (c >> 7);

if c is unsigned and non-volatile, the compiler will detect that the intended operation is a rotate left of 1 bit and will encode the output using the PIC MCU rotate instructions. A rotate left of 2 bits would be implemented with code like:

c = (c << 2) | (c >> 6);

This code optimization will also work for integral types larger than a char. If the opti- mization cannot be applied, or this code is ported to another compiler, the rotate will be implemented, but typically with shifts and a bitwise OR operation.

C Language Features

3.6.4

Division and modulus with integral types

The sign of the result of division with integers when either operand is negative is imple- mentation specific. Table 3-5 shows the expected sign of the result of the division of operand 1 with operand 2 when compiled with HI-TECH C.

In the case where the second operand is zero (division by zero), the result will always be zero.

Related documents