Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does it mean for a char to be signed?

Given that signed and unsigned ints use the same registers, etc., and just interpret bit patterns differently, and C chars are basically just 8-bit ints, what's the difference between signed and unsigned chars in C? I understand that the signedness of char is implementation defined, and I simply can't understand how it could ever make a difference, at least when char is used to hold strings instead of to do math.

like image 685
dsimcha Avatar asked Jan 16 '09 18:01

dsimcha


People also ask

What do you mean by signed char?

A signed char is a signed value which is typically smaller than, and is guaranteed not to be bigger than, a short . An unsigned char is an unsigned value which is typically smaller than, and is guaranteed not to be bigger than, a short .

Why do we use signed char?

You would use a signed char when you need to represent a quantity in the range [-128, 127] and you can't (for whatever reason) spare more than a single byte to do it.

Can char be signed or unsigned?

@eSKay: yes, char is the only type that can be signed or unsigned. int is equivalent to signed int for example.

Is char signed or not?

The C and C++ standards allows the character type char to be signed or unsigned, depending on the platform and compiler. Most systems, including x86 GNU/Linux and Microsoft Windows, use signed char , but those based on PowerPC and ARM processors typically use unsigned char .


2 Answers

It won't make a difference for strings. But in C you can use a char to do math, when it will make a difference.

In fact, when working in constrained memory environments, like embedded 8 bit applications a char will often be used to do math, and then it makes a big difference. This is because there is no byte type by default in C.

like image 102
Nick Fortescue Avatar answered Sep 21 '22 11:09

Nick Fortescue


In terms of the values they represent:

unsigned char:

  • spans the value range 0..255 (00000000..11111111)
  • values overflow around low edge as:

    0 - 1 = 255 (00000000 - 00000001 = 11111111)

  • values overflow around high edge as:

    255 + 1 = 0 (11111111 + 00000001 = 00000000)

  • bitwise right shift operator (>>) does a logical shift:

    10000000 >> 1 = 01000000 (128 / 2 = 64)

signed char:

  • spans the value range -128..127 (10000000..01111111)
  • values overflow around low edge as:

    -128 - 1 = 127 (10000000 - 00000001 = 01111111)

  • values overflow around high edge as:

    127 + 1 = -128 (01111111 + 00000001 = 10000000)

  • bitwise right shift operator (>>) does an arithmetic shift:

    10000000 >> 1 = 11000000 (-128 / 2 = -64)

I included the binary representations to show that the value wrapping behaviour is pure, consistent binary arithmetic and has nothing to do with a char being signed/unsigned (expect for right shifts).

Update

Some implementation-specific behaviour mentioned in the comments:

  • char != signed char. The type "char" without "signed" or "unsinged" is implementation-defined which means that it can act like a signed or unsigned type.
  • Signed integer overflow leads to undefined behavior where a program can do anything, including dumping core or overrunning a buffer.
like image 32
Ates Goral Avatar answered Sep 23 '22 11:09

Ates Goral