Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conversion warning when adding two uint8_t

I have the following C code:

typedef unsigned char uint8_t;

void main(void) {
    uint8_t a = 1, b = 2, res;
    res = a + b;
}   

When I compile this code using gcc -Wconversion, I get the following warning:

test.c: In function 'main':
test.c:5:10: warning: conversion to 'uint8_t' from 'int' may alter its value [-Wconversion]

Can someone please explain why this warning appears? All three variables are of type uint8_t, so I don't really understand where the int comes from.

like image 527
watain Avatar asked Jan 24 '14 14:01

watain


People also ask

What is the difference between Uint8 and uint8_t?

The difference between Uint8 and uint8_t will depend on implementation, but usually they will both be 8 bit unsigned integers. Also uint8_t and uint16_t are defined by C (and maybe C++) standard in stdint. h header, Uint8 and Uint16 are non-standard as far as I know.

What is __ uint8_t?

uint8_t is available on systems where there is a native type with exactly eight bits. If there is no such type, then uint8_t is not defined. This has nothing to do with unix, linux, OS X, or whatever. It's about the hardware that the program is running on.

Is uint8_t always unsigned char?

If it exists, uint8_t must always have the same width as unsigned char . However, it need not be the same type; it may be a distinct extended integer type. It also need not have the same representation as unsigned char ; for instance, the bits could be interpreted in the opposite order.

Should I use uint8_t?

If the intended use of the variable is to hold an unsigned numerical value, use uint8_t; If the intended use of the variable is to hold a signed numerical value, use int8_t; If the intended use of the variable is to hold a printable character, use char.


2 Answers

I don't really understand where the int comes from.

int comes from the C language standard. All operands of arithmetic operators are promoted before performing their operation. In this case uint8_t is promoted to an int, so you need a cast to avoid the warning:

res = (uint8_t)(a + b);

Here is how the standard defines integer promotions:

6.3.1.1 If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.

Since int can hold all possible values of uint8_t, a and b are promoted to int for the addition operation.

like image 105
Sergey Kalinichenko Avatar answered Sep 20 '22 10:09

Sergey Kalinichenko


Just to add to the existing answer about integer promotions, it might also be worth explaining what -Wconversion is warning you about.

Since a and b are both uint8_ts, the result of a + b might not fit in another uint8_t. By assigning the result back into a uint8_t, you force the compiler to perform a conversion which might change the value. Hence, the res variable might not actually represent the actual value of a + b.

For example, if a and b were both 0xff, then:

  • a + b is 0x1fe and has type int
  • (uint8_t)(a + b) is 0xfe
like image 28
benj Avatar answered Sep 19 '22 10:09

benj