Fundamental C - Expressions
Tuesday, 24 May 2022
Article Index
Fundamental C - Expressions
Operators
The Rules
C99

The rules, known as the usual arithmetic conversions seem complicated. The C99 standard says:

1. If both operands have the same type, then no further conversion is needed.

2. Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.

3. Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

4. Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.

5. Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

The most worrying part of this specification is point 3 as converting a signed integer to an unsigned of the same rank seems to invalidate the arithmetic. You have to remember that two’s-complement arithmetic works even if you consider the value to be unsigned. For example:

```unsigned int myUnsigned=1;
int myInt=-1;
myInt=myInt+myUnsigned;
printf("%d \n",myInt);```

In this case the signed int is converted to unsigned and it looks as though we are going to get the answer 2 as the negative is lost. This is not how it works. The signed int is converted to an unsigned int with the same bit pattern. When added together the roll over occurs and the result is the same in two's-complement. That is, it prints 0 and we have the correct answer.

This doesn’t mean that you cannot get the wrong answer. For example:

```unsigned int myUnsigned=UINT_MAX;
int myInt=1;
myInt=myInt+myUnsigned;
printf("%d \n",myInt);```

In this case you will still see zero printed, which in this case is probably the wrong answer. Again we have the same bit patterns. The UINT_MAX is -1 when regarded as a signed int and hence the final result is zero. To get the correct answer we need to explicitly use a cast to long long:

```unsigned int myUnsigned=UINT_MAX;
int myInt=1;
long long mylong= (long long)myInt+(long long)myUnsigned;
printf("%lld \n",mylong);```

In fact, we don’t need to cast myInt to long long because the rules will promote it to the same as myUnsigned.

Notice that these casts are only performed in expressions, including comparison operators, and bitwise operators. They are not performed for assignment operators. In most cases the result of expressions involving mixed types give you the correct answer but if in doubt use explicit casts.

A common idiom, however, is to rely on the rules to change integer arithmetic into floating-point arithmetic. For example:

```int myInt=1;
float ans=myInt/100;```

gives the answer 0 as integer division is performed before the result is converted to a float. However:

```int myInt=1;
float ans=myInt/100.0;```

gives the result 0.01 as the literal is now a float and hence myInt is automatically converted to a float.

#### In chapter but not in this extract

1. Side Effects
2. Postfix and Prefix Increment
3. Conditional and Comma
4. Sequence Points and Lazy Evaluation

## Summary

• Expressions form a sophisticated programming language in their own right consisting of operators with precedence and associativity rules.

• Casts allow bit patterns to represent different things.

• Widening casts always preserve the original value.

• Narrowing casts only preserve the original value if it is representable in the smaller type.

• The rules for mixed type expressions are complicated - if in doubt use an explicit cast.

• Sequence points determine when the side effects of an expression are determined and sequence point rules make some expressions undefined.

• Logical OR and AND are lazy evaluated which means that the right-hand expression may never be evaluated and hence may never cause any side effects.

• If you find you are having to work out sequence points and rules the chances are you are writing obscure code.

## Related Articles

Remote C/C++ Development With NetBeans

Raspberry Pi And The IoT In C

Getting Started With C/C++ On The Micro:bit

## Fundamental C: Getting Closer To The Machine

#### Now available as a paperback and ebook from Amazon.

Extract Dependent v Independent
& Undefined Behavio
2. Getting Started With C Using NetBeans
3. Control Structures and Data
4. Variables
Extract Variables
5. Arithmetic  and Representation
Extract Arithmetic and Representation
6. Operators and Expression
Extract: Expressions
Extract Side Effects, Sequence Points And Lazy Evaluation
First Draft of Chapter: Low Down Data
8. Arrays
Extract  Simple Arrays
Extract  Ennumerations
9. Strings
Extract  Simple Strings

Extract: String I/O ***NEW!!
10. Pointers
Extract  Starting Pointers
Extract  Pointers, Cast & Type Punning
11. Structs
Extract Basic Structs
Extract Typedef
12. Bit Manipulation
Extract Basic Bits
Extract Shifts And Rotates
13. Files
Extract Files

Extract Random Access Files
14. Compiling C – Preprocessor, Compiler, Linker
Extract Compilation & Preprocessor

Also see the companion volume: Applying C

<ASIN:1871962609>

<ASIN:1871962463>

<ASIN:1871962617>

<ASIN:1871962455>

 Introducing The LiveCodes Code Playground20/09/2023LiveCodes is a groundbreaking code playground with unique features. And it is free too. Currently in Beta. Let's look into it. + Full Story SQLite 3.43 Released 05/09/2023SQLite 3.43 has been released with new support for Contentless-Delete FTS5 Indexes, as well as better JSON processing. + Full Story More News