IamIC IamIC - 1 month ago 6
C Question

C / C++ best practices with signed / unsigned ints and function calls

I am asking this question for two different languages: C and C++.

What is best practice when calling functions that have an opposite integer sign expectation to what we require in our code?

For example:

uint32 _depth; // uint32 = DWORD
int depth;

_BitScanForward(&_depth, (uint32)input); // DWORD, DWORD
depth = (int)_depth;

_BitScanForward is expecting DWORD (uint32) parameters. The variable
is of int16 type and I need to process the result
as an int32 in my code.

  1. Do I need to care about casting
    as shown? I know the complier will probably do it for me, but what is best practice?

  2. Is it acceptable to declare
    as int32 and therefore avoid having to cast it afterwards as shown?


My comment about the complier is based on experience. I wrote code that compiled with no warnings in VS but crashed on execution. Turned out I was calling a function with an incorect width int. So I don't leave this topic up to the compiler any more.


The answers are helpful, thanks. Let me refine my question. If there are no width issues, i.e. the function is not expecting a narrower int than what is being passed in (obvioulsy will fail), then is it okay to rely on the compiler to handle sign and width differences?


It is very important to write an explicit cast when going from any integer type that is narrower than int to any integer type that is the same width or wider than int. If you don't do this, the compiler will first convert the value to int, because of the "integer promotion" rules, and then to the destination type. This is almost always wrong, and we wouldn't design the language this way if we were starting from scratch today, but we're stuck with it for compatibility's sake.

System-provided typedefs like uint16_t, uint32_t, WORD, and DWORD might be narrower, wider, or the same size as int; in C++ you can use templates to figure it out, but in C you can't. Therefore, you may want to write explicit casts for any conversion involving these.