You probably want to use -Wconversion
24 / 12 / 2025

Consider these examples of implicit conversions in C:

void foo(unsigned int x)
{
  int b = -5;

  /* ... */

  if (b < x) {
    /*
     * If b < 0, the check will always fail!
     * b is first converted to unsigned int before comparison.
     */
  }
}

/*
 * If we first wrote the code using type int for coeff,
 * but later refactored to use float as below,
 * but forgot to update type of diff, we might get a rounding
 * and possibly an undesired behavior.
 */
float coeff = /* ... compute some value ... */;
int diff = old_coeff - coeff;

You can ask the compiler to always warn on implicit conversions, so that user is expected to explicitly mark conversions and hopefully catch some mistakes.

With -Wconversion (-Wfloat-conversion, -Wsign-conversion, -Wsign-compare) you get:

a.c: In function ‘foo’:
a.c:7:11: warning: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Wsign-compare]
    7 |     if (b < x) {
      |           ^
a.c: In function ‘bar’:
a.c:26:16: warning: conversion from ‘float’ to ‘int’ may change value [-Wfloat-conversion]
   26 |     int diff = old_coeff - coeff;
      |                ^~~~~~~~~
a.c:26:9: warning: unused variable ‘diff’ [-Wunused-variable]
   26 |     int diff = old_coeff - coeff;
      |         ^~~~

As of day of writing this post, gcc and clang only catch -Wsign-compare with the usual "-Wall -Wextra".

Practical examples would be:

Automatic checking against runtime narrowing conversions

There is also an interesting talk Bjarne gave about concepts. He showed how you would use them to create a class wrapper in C++ to catch narrowing conversions at runtime. Arguably, using std::expected might be a better API for some use cases, but the idea is still general.