Fundamental C - Expressions
Written by Harry Fairhead   
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.

  1. About C
      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
  7. Functions Scope and Lifetime
  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>

 

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

Banner


.NET 9 Released
18/11/2024

.NET 9 has been released with a number of performance improvements and new features designed to help developers use AI.



AI Propels Python To Top Language on GitHub
30/10/2024

This year's Octoverse Report reveals how AI is expanding on GitHub and that Python has now overtaken JavaScript as the most popular language on GitHub. The use of Jupyter Notebooks has also surged.


More News

espbook

 

Comments




or email your comment to: comments@i-programmer.info

 



Last Updated ( Tuesday, 24 May 2022 )