c language · medium

C: char Signedness & sizeof Quirks

C has three distinct character types — char, signed char, and unsigned char — and the signedness of plain char is implementation-defined (typically signed on x86 desktops, unsigned on many ARM platforms). As a result, a byte with its high bit set such as '\x80' may be negative or positive depending on the target, so testing s[0] < 0 or using a plain char to index a 256-entry table is non-portable; use unsigned char for raw bytes, hashing, and table indices (and note that <ctype.h> functions require arguments representable as unsigned char or EOF). sizeof(char) is 1 by definition because char is the unit in which all sizes are measured (a byte is CHAR_BIT bits, at least 8), yet in C a character constant like 'A' has type int, so sizeof('A') is 4 — a favorite trick question, and a point where C differs from C++, where 'A' is a char with sizeof 1; the int-ness is otherwise harmless thanks to integer promotion. This is also why getchar, fgetc, and getc return int rather than char: they must represent all 256 possible byte values plus a distinct EOF (usually -1), so storing the result directly in a char can lose the EOF signal or let a genuine 0xFF byte falsely compare equal to EOF — always read into an int, test for EOF, and only then narrow to char.

🔑 Key line

C char quirks: plain char's signedness is implementation-defined (use unsigned char for raw bytes/indices); sizeof(char)==1 always but a char constant 'A' has type int in C (sizeof 4, unlike C++); getchar/fgetc return int to distinguish all 256 bytes from EOF — read into int before narrowing.

The code

char c = 'A'; // plain char: signed OR unsigned (impl-defined)
sizeof(char) == 1; // always 1, by definition
sizeof('A') == 4; // in C, a char constant has type int!
char ch = getchar(); // BUG: can't distinguish EOF (-1) on some impls
int ic = getchar(); // correct: int holds all 256 chars + EOF
char* s = "\x80"; if (s[0] < 0) ... // depends on char signedness!

What this lesson walks through

  1. 01Plain char has implementation-defined signedness
  2. 02sizeof(char)==1 but a char constant is int
  3. 03Gotcha — char signedness + getchar returns int
  4. 04getchar returns int, not char

C has THREE distinct char types: char, signed char, and unsigned char. Whether plain char is signed or unsigned is implementation-defined (signed on x86/most desktops, unsigned on many ARM). So a byte with the high bit set, like '\x80', may be negative or positive depending on the platform — code that tests s[0] < 0 or uses char to index a 256-entry table is non-portable. Use unsigned char for raw bytes and table indices.

See it animated — step by step, at your own pace

Unlock the full interactive walkthrough of C: char Signedness & sizeof Quirks and 100+ animated C++ interview lessons.

← Previous
C: Preprocessor Macro Pitfalls
Next →
Deadlock & the 4 Coffman Conditions