1

I want to see a warning or an error if the developer in C Code is comparing different data types. I am using the gcc arm none eabi and I have tried the following code and the following compiler flags correspondingly.

uint8_t foo = 0;
int16_t bar = -1;

int main() {
  while(1) {
    if (foo==bar) return 0;
  }
}

Compiler Options

-Wsign-compare -Wall -Wextra

But I cannot see any error or warning, Why? Could you help me?

pop rock
  • 517
  • 1
  • 6
  • 14
  • 5
    The values are promoted to `int` before comparison; they have the same type when promoted. That may be why you don’t get any warning for the comparison. You should get a warning about the `return` with no value in a function returning an `int`, unless perhaps the compiler deduces the return will never be executed. – Jonathan Leffler Sep 12 '18 at 09:59
  • 3
    https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options "*`-Wsign-compare` - Warn when a comparison between signed and unsigned values could produce an incorrect result when the signed value is converted to unsigned.*" `bar` is not converted to an unsigned type. – melpomene Sep 12 '18 at 10:04
  • @JonathanLeffler Thank you for the reply, but I want to deny the developers to use this kind of comparison. Maybe this code is simple but in complex software maybe it will be a very awful bug. – pop rock Sep 12 '18 at 10:05
  • 1
    `-Wsign-compare` is only for C++ – David Ranieri Sep 12 '18 at 10:05
  • @melpomene could you explain more about your answer? – pop rock Sep 12 '18 at 10:07
  • 4
    @KeineLust Documentation seems to imply that it's available also on C: *"-Wsign-compare Warn when a comparison between signed and unsigned values could produce an incorrect result when the signed value is converted to unsigned. In C++, this warning is also enabled by -Wall. **In C, it is also enabled by -Wextra.** "* – user694733 Sep 12 '18 at 10:07
  • @KeineLust How could I use in C something similar? – pop rock Sep 12 '18 at 10:07
  • 1
    @poprock 1) I only wrote a comment, not an answer. 2) What's unclear about it? – melpomene Sep 12 '18 at 10:08
  • @KeineLust No, it's also for C. See, see the manual https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wsign-compare – ikkentim Sep 12 '18 at 10:09
  • 1
    @melpomene why is not converted to an unsigned type? – pop rock Sep 12 '18 at 10:10
  • What about an analyse tool like PC-Lint? – Mike Sep 12 '18 at 10:10
  • Oops, sorry, `-Wall` turns on this flag only in C++ – David Ranieri Sep 12 '18 at 10:10
  • 1
    @poprock because `uint8_t` and `int16_t` both fit into `int`, therefore they'll be promoted to int. And it's *promotion*, not *conversion*. All types narrower than int will always be promoted to int – phuclv Sep 12 '18 at 10:11
  • 1
    @poprock Because, as JonathanLeffler said, they're both converted to `int`. As for why, see https://stackoverflow.com/a/46073296/1848654. – melpomene Sep 12 '18 at 10:11
  • @phuclv Are you sure that is it ok? I mean, it is safe for the software or maybe in complex situations exist an awful bug? – pop rock Sep 12 '18 at 10:17
  • 2
    @JonathanLeffler *You should get a warning ...* Not on `main()`. Per [**5.1.2.2.3 Program termination**](https://port70.net/~nsz/c/c11/n1570.html#5.1.2.2.3): "... reaching the } that terminates the main function returns a value of 0 ..." – Andrew Henle Sep 12 '18 at 10:24
  • This should be caught in static analysis, for example: http://adlint.sourceforge.net/pmwiki/upload.d/Main/users_guide_en.html#W0245 – mnistic Sep 12 '18 at 10:25
  • 1
    @AndrewHenle — Before it was edited, the return after the if had no value specified. I agree that if the infinite loop terminates, falling off the end of main in C99 or later is equivalent to returning zero. – Jonathan Leffler Sep 12 '18 at 10:27
  • There's nothing dangerous with *comparing different datatypes* per se. People compare like that all the time, for example int and long. It's just that comparing **types with different signness** may produce unexpected result due to the change in *value*, and that was coverered with `-Wsign-compare`. In this case all the values are preserved like chux said, and the output won't surprise you like `-1 > 2U` – phuclv Sep 12 '18 at 14:35

1 Answers1

2

How to get a warning, if the C Code comparing different datatypes?

== causes both operands to to go though an implicit conversion per their relative integer conversion rank. To get a warning, do a comparison that after integer promotions, the operands differ in sign-ness.

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. C11dr §6.3.1.1 2

A key concept to remember is that integer promotions never changes the value, only the type. With no value change, the compare happens with no "surprises".

It is conversion that may change the value. E.g. int -1 --> unsigned UINT_MAX.


I cannot see any error or warning, Why?

With foo8 == bar below, both foo8 and bar are promoted to int. There is nothing significant to warn about. The compare is well defined for all value combinations of bar, foo8 - no surprises. That is C.

uint8_t foo8 = 0;
int16_t bar = -1;
uint32_t foo32 = 0;

int main(void) {
  if (foo8 == bar)  return 1;
  if (foo32 == bar) return 2;
}

With foo32 == bar, foo32 becomes unsigned (or unsigned long) and bar is promoted to int. With various compiler options, you can readily get a warning like

warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

In this later case, to compare an int over its [INT_MIN...INT_MAX] range to an unsigned over its [0...UINT_MAX] range and make sure comparing -1, UINT_MAX fails, code could use:

// if (foo32 == bar) return 2;
if (bar >= 0 && foo32 == (unsigned)bar) return 2;
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256