Difference between char and uint8_t

Quote from learncpp.com: "std::int8_t and std::uint8_t likely behave like chars instead of integers".

My question is: what difference in behavior is there?

For example:

char myVal = 1;

Serial.print(myVal);

The serial monitor will show: 1

Is the actual value in RAM 0x01 (1 in decimal) or 0x31 (1 in ASCII code)?

Does the Arduino IDE treat char differently than uint8_t? And if not: what is the difference that learncpp.com warns for?

The Arduino Reference doesn't help much either: "It's recommended to only use char for storing characters. For an unsigned, one-byte (8 bit) data type, use the byte data type". (I tried to use byte. It doesn't compile.)

1 Like

How for what? Please post the sketch that uses byte and does not compile.

a7

The code had some other mistake.

I don’t have that sketch anymore. It was months ago. I did replace it by uint8_t and it compiled. I use uint8_t eversince.
I don’t do much with texts, but the question still bugs me.

Reproduce the error, post the code and the error message, otherwise you are unlikely to get help with it.

It‘s not a program that I like to fix, I fixed by using uint8_t. I’m searching for background information that Google and other sources don’t provide. And possibly, in the future, when I’m going to use texts, it may or may not become important.

And yes, it is possible that that sketch had other mistakes, that were fixed one by one.
I was trying to figure out Arduino (still am, by the way.)

1. If we respect that char data type is used for storing characters, then the above declaration should be:

char myVal = '1'; //memory location holds: 00110001 = ASCII code of '1' 
Serial.print(myVal); //shows: 1

2. What do you expect to see on Serial Monitor after the execution of the following codes?

char myVal = '1'; 
Serial.print(myVal, DEC); //shows: ?

3. What do you expect to see on Serial Monitor after the execution of the following codes?

char myVal1 = 0x41;
byte myVal2 = 0x41; 
Serial.print(myVal); //shows: A
Serial.print(myVal2);   //shows: 65

The print() method checks the data type and if it is byte, then applies base 10 (default, DEC) to display the value of myVal2 variable.

The following code will show 41 on the Serial Monitor.

Serial.print(myVal2, HEX);  //shows: 41

4. Why is uint16_t instead of int?
In 8-bit architecture like UNO, the int allocates 16-bit memory space for a variable.

In 32-bit architecture like DUE/ESP32, the int allocates 32-bit memory space for a variable.

In order to ensure that the compiler allocates 16-bit memory space for a variable regardless of MCU architecture(8-bit/16-bit/32-bit), the recommended data type is uint16_t.

5. Someone else may clarify uint8_t.

Now things are starting to make sense. Please tell me if I'm wrong:

Because of the quotes, '1', the compiler loads the value 0x49 (1 in ASCII).

Because of the datatype, char, the Serial.print function chooses to output this value, by the serial monitor translated to the letter 1.

But if my uint8_t contains 0x41, I can't make Serial.print output this ASCII code. (Never mind, I'll use Serial.write)

Not all questions are answered yet. I figured out that math functions react different to int and unsigned int.

Let's suppose:

Char myVal = 0x41;

myVal *= 3;

What will happen?

I should try this.

Show me an example code with output where that happens.

This is ASCII Code Table which shows that the ASCII Code of '1' is 00110001 (0x31 in HEX-base and 49 in DEC-base).

In UNO, byte and uint8_t are synonyms.

Indeed they are.

Some interesting typedef statements from Arduino.h:

typedef unsigned int word;

#define bit(b) (1UL << (b))

typedef bool boolean;
typedef uint8_t byte;

char is an 8 bit signed variable (holds values from -128 to 127), mostly used to store ASCII characters (7 bit).
byte is an 8 bit unsigned variable (holds values 0 to 255), used to store small numbers like pin numbers and such. Not a universally recognized variable name.

Char myVal = 0x41;

myVal *= 3;

Prints: -109 or 0xFFFFFF93

Next riddle: where is char translated to a 32-bit number?

I hadn't found arduino.h yet. And I tried to find all #includes for UNO R3 and Nano Every. So these miss out on the arduino.h (meant for 32-bit processors).

Programming Language is mostly a rule-based language. So, it is very important that we note down the rules as we progress in learning the language.

When you multiply 0x41 by 3 (0x03), the result is 0xC3, which will be seen by the print() method as 2's complement number (because MSBit of C3 is 1). The decimal equivalent of C3 = -1 x 27 + 67 = - 61.

  char myVal = 0x41;
  myVal *=3;   //1100 0011 
  Serial.print(myVal, DEC);  //shows: - 61

On my Linux box it's at /home/username/arduino-1.8.5/hardware/arduino/avr/cores/Arduino.h.

Found it. I have 1 Nano Every and 1 UNO R3, so it's not relevant for me.

Are word, byte, and boolean still keywords?