Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to fix errors caused by -Wconversion?

Tags:

c

gcc

I have a piece of fake/sample code:

#include <stdint.h>

uint8_t func(uint16_t val0, uint16_t val1, uint16_t val2)
{
    uint8_t r;
    val0 += 0x7F;
    val1 += (uint16_t)0x7F;
    val2 += 0x7FU;
    r = (uint8_t)((val0+val1+val2) >> 8);
    r <<= (uint8_t)(val2 & 0x3);
    return r;
}

Here are the errors I get:

$ gcc -Wall -Wextra -Wconversion -O0 module.c -c -o module.o 
module.c: In function 'func':
module.c:6:10: warning: conversion from 'int' to 'uint16_t' {aka 'short unsigned int'} may change value [-Wconversion]
    6 |  val0 += 0x7F;
      |          ^~~~
module.c:7:10: warning: conversion from 'int' to 'uint16_t' {aka 'short unsigned int'} may change value [-Wconversion]
    7 |  val1 += (uint16_t)0x7F;
      |          ^
module.c:8:10: warning: conversion from 'unsigned int' to 'uint16_t' {aka 'short unsigned int'} may change value [-Wconversion]
    8 |  val2 += 0x7FU;
      |          ^~~~~
module.c:10:8: warning: conversion from 'int' to 'uint8_t' {aka 'unsigned char'} may change value [-Wconversion]
   10 |  r <<= (uint8_t)(val2 & 0x3);
      |        ^

The example shows some ways I tried to fix the problem (e.g. cast)

Any suggestion?

EDIT:

modified example

like image 451
mastupristi Avatar asked Oct 27 '25 05:10

mastupristi


1 Answers

This question illustrates why -Wconversion is so overzealous that it's largely useless.

In C, there is no arithmetic smaller than int. For example:

val0 += 0x7F;

is evaluated as if it were

val0 = (int)val0 + 0x7F;

The assignment back to val0 without a cast then triggers -Wconversion. In some sense this is a legitimate warning: the + operator does not overflow, but assiging the result back may lose part of the result, and the compiler is telling you this (albeit awkwardly).

If you're going to use -Wconversion, you essentially can't use compound assignment operator (like +=) with smaller-than-int types. You need to write out the equivalent form and use a cast to indicate that you intend for the lossy conversion to happen. For instance here you would write:

val0 = (uint16_t)(val0 + 0x7F);

I don't think this is terribly good style, but some coding standards/policies (MISRA, I think, for one) mandate it.

like image 87
R.. GitHub STOP HELPING ICE Avatar answered Oct 29 '25 22:10

R.. GitHub STOP HELPING ICE



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!