4

Do we need a cast in this situation?:

#include <stdio.h>
#include <stdint.h>

int main(){

  // Say we're working with 32-bit variables.
  uint32_t a = 123456789;
  uint32_t b = 5123412;
  uint32_t c = 123049811;

  // We want to use 64-bit arithmetic at some intermediate stage, 
  // e.g. the a*b product here. After dividing by 'c', the result
  // again fits into a 32-bit unsigned, 'result'.
  uint32_t result = (uint64_t)a*b/c;

  // QUESTION HERE: Should we cast before the assignment? I.e.:
  //uint32_t result = (uint32_t)( (uint64_t)a*b/c );

  // Either way the result turns out OK on my system.
  printf("%u\n", (unsigned)result);

}
Douglas B. Staple
  • 10,510
  • 8
  • 31
  • 58
  • 3
    This is much a question of debate, I would prefer only to have casts when strictly necessary. Casts are syntactically difficult to find and may hide much bigger problems, since now the compiler assumes that you know what you are doing. The cast in the `printf` is a good example: you may cast significant parts away. (Think of a system with 16 bit `int`.) The correct way here is to use `printf("%" PRIu32 "\n", result)`. – Jens Gustedt Oct 27 '13 at 21:05
  • @Jens Whoa. I've never seen that before; I've had a terrible time printing fixed-width types. I have to go now, but I'm going to take a close look at that later on. – Douglas B. Staple Oct 27 '13 at 21:14
  • I can only recommend reading through the standard, it is finally not as difficult to read, and has a lot of pearls like that. – Jens Gustedt Oct 27 '13 at 21:42

3 Answers3

2

For any assignment a = b;, the value of b is converted to a value of the type of a, provided that is possible, and that converted value is assigned to a. So the outermost cast which you propose is redundant.

Not all such conversions are possible, though, and a cast can be used to force a conversion, or to create a chain of legitimate conversions where a direct one doesn't exist, as in this next example:

foo x;

bar * y = (void *)&x;

There is no implicit conversion from foo * to bar *, but there is an implicit conversion from any object pointer type to and from void * (although it is unspecified whether y has a usable or useful value).

Another use of explicit casts is when it changes the meaning of a value -- a typical example is when you want to treat a byte of I/O as an unsigned value. Since char can be either signed or unsigned, converting a char directly to an unsigned int may give the wrong answer. For instance, we want -1 to be the value 255, not -1. So you need:

char b = get_input();

unsigned int value = (unsigned char)b;

The conversion from char to unsigned char always produces the "expected", unsigned byte value, and then it's fine to convert this to an unsigned integer.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Yes, that's what I thought. For some reason I caught myself writing the cast. I always code alone so I don't really have anyone to double check this kind of basic stuff against. – Douglas B. Staple Oct 27 '13 at 20:49
  • @KerrekSB Due to the lack of PMs I'll just post the comment here.. Concerning the [question on cartesian products](http://stackoverflow.com/q/9122028/420683), I proposed a (rather short) fix in the linked live example (the out-commented parts) -- I found your solution to be quite compact and straight-forward. – dyp Oct 27 '13 at 23:12
  • @DyP: Do you want to go fix it yourself? I can undelete it. – Kerrek SB Oct 27 '13 at 23:25
1
// QUESTION HERE: Should we cast before the assignment? I.e.:
//uint32_t result = (uint32_t)( (uint64_t)a*b/c );

The cast is not necessary here.

C never requires a cast when assigning a value from one arithmetic type to an object of a different arithmetic type. There is an implicit conversion between all arithmetic types.

Now be aware that some compiler may warn. For example if the right operand is a constant expression and it is not representable in the type of the left operand, gcc warns.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • That kind of warning was the reason for the question. Like you say, there's no warning (and no problem) in this situation, though. – Douglas B. Staple Oct 27 '13 at 20:52
  • @DouglasB.Staple and for the sake of completeness of my answer, MISRA-C would require a cast here (to make the conversion to a narrower type explicit for the reader). – ouah Oct 27 '13 at 20:54
  • Well that would imply to me that it's good practice to put the explicit cast, even if it's redundant? – Douglas B. Staple Oct 27 '13 at 20:56
  • 2
    @DouglasB.Staple not necessarily, a lot of MISRA rules are disputed. Personally, I don't like unnecessary stuff in programming and I would not put the cast. – ouah Oct 27 '13 at 20:59
  • 1
    Anything that's a MISRA requirement calls for major skepticism. – R.. GitHub STOP HELPING ICE Oct 27 '13 at 23:53
0

6.3 Conversions:

Several operators convert operand values from one type to another automatically. This sub-clause specifies the result required from such an implicit conversion, as well as those that result from a cast operation (an explicit conversion).

6.5.16.1 Simple assignment:

In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264