7. BASIC TYPES
• Systems of numeration
Numeric Types
• C’s basic types include integer types and floating types.
• Integer types can be either signed or unsigned.
• A value of a signed type can be either negative, zero, or
positive.
• A value of an unsigned type must be zero or positive.
Integer Types
• C provides six integer types:
• C99 also supports the long long int type, whose values
typically range from –263 to 263 – 1, and unsigned long
long int, whose values typically range from 0 to 264 – 1.
Integer Types
• Integer types can be abbreviated by omitting the
word int:
long i; /* same as long int i; */
• In general, avoid using unsigned types.
• <limits.h>
• INT_MIN
• INT_MAX
Integer Constants
• Integer constants may be written in decimal (base 10),
octal (base 8), or hexadecimal (base 16).
• Decimal integer constants contain digits, but must not
begin with a zero:
15 255 32767
• Octal integer constants contain only digits between 0
and 7, and must begin with a zero:
017 0377 077777
Integer Constants
• Hexadecimal integer constants contain digits between 0
and 9 and letters between A and F (or a and f), and
always begin with 0x:
0xf 0xff 0x7fff
•
The letters in a hexadecimal constant may be either upper or lower
case.
Force type
15L 0377L 0x7fffL
15U 0377U 0x7fffU
0xffffffffUL
Integer Overflow
• Signed
• Unsigned
Reading and Writing Integers
• When reading or writing an unsigned integer, use the
letter u (decimal), o (octal), or x (hex) in the conversion
specification:
unsigned int
printf("%u",
printf("%o",
printf("%x",
u;
u); /* writes u in base 10 */
u); /* writes u in base 8 */
u); /* writes u in base 16 */
• When reading or writing a short integer, put the letter h in
front of d, o, x, or u:
short int s;
printf("%hd", s);
Reading and Writing Integers
• When reading or writing a long integer, put the letter l in
front of d, o, x, or u:
long int l;
printf("%ld", l);
Floating Types
• C supports three floating types:
(Ranges shown are typical.)
Floating Constants
• Floating constants can be written in either fixed-point
notation or scientific notation.
• Examples of fixed-point notation:
57.0 57.
• Examples of scientific notation:
57.0e0 57.0E0 57e0 5.7e1 5.7e+1 .57e2 570.e-1
• Floating constants are by default represente as double:
57.0e0 57.0E0 57e0 5.7e1 5.7e+1 .57e2 570.e-1
• Force type:
57.0f 57.0L
Reading and Writing FloatingPoint Numbers
• When reading (not writing) a value of type double, put
the letter l in front of e, f, or g:
double d;
scanf("%lf", &d);
• Warning: double values must be written using e, f,
or g, just like float values:
double d;
printf("%f", d);
In C99, however, using %le , %lf, or %lg to print a double value is
legal.
Reading and Writing FloatingPoint Numbers
• When reading or writing a value of type long double,
put the letter L in front of e, f, or g:
long double ld;
printf("%Lf", ld);
The char Type
• In addition to the numeric types, C provides one other
basic type: char, the character type.
• A variable of type char can be assigned any character in
the underlying character set:
char c;
c = 'a';
c = '0';
c = ' ';
• Character constants are written in single quotes, not
double quotes.
The char Type
• C represents values of type char as integers. Any
operation that is allowed for integers is also legal for
characters:
if ('a' <= c && c <= 'z')
c = c - 'a' + 'A'; /* converts c to upper case */
<ctype.h>
c=toupper(c);
• Also, characters and integers can be mixed in
expressions:
c = 'a';
c = c + 1; /* c now contains the letter 'b' */
Numeric Escapes
• Storing a special character in a variable requires the use
of an escape sequence:
c = '\n'; /* store new-line character in c */
• Numeric escapes are used for characters that cannot be
represented by character escapes.
• There are two kinds of numeric escapes:
Octal
Hexadecimal
Numeric Escapes
• An octal escape sequence is written \ddd, where ddd is a
one-, two-, or threedigit octal number representing the
position of the character in the underlying character set
(usually ASCII). Examples:
null character \0
escape character \33
• A hexadecimal escape sequence consists of \x followed
by a hexadecimal number. Examples:
null character \x0
escape character \x1b (or \x1B)
• A numeric escape is enclosed in single quotes when
used as a character constant:
c = '\0'; /* store null character in c */
c = '\x1b'; /* store escape character in c */
Universal Character Names
• C99 also provides universal character names, which
have the form \udddd or \Udddddddd, where each d is a
hexadecimal digit.
• Each dddd or dddddddd sequence is a UCS (Universal
Character Set) code.
• Unicode is closely related to UCS, and its codes are
compatible with those of UCS.
• Universal character names that represent letters and
digits are allowed in identifiers.
Reading and Writing Characters
• To read or write a character using scanf or printf,
use the %c conversion specification:
scanf("%c", &c);
printf("%c", c);
• A faster alternative: Use getchar and putchar instead
of scanf and printf:
c = getchar();
putchar(c);
Reading and Writing Characters
• Neither scanf nor getchar skips white space before
reading a character.
• To read the first nonblank character, use scanf in the
following way:
scanf(" %c", &c); /* skip white space, then read
c */
• To detect the end of an input line, test whether the
character read by scanf or getchar is a new-line
character.
Examples
while (getchar() == ' ');
while (getchar() != '\n');
while ((ch = getchar()) != '\n')
{//process ch
}
Type Conversion
• C provides two methods of changing the type of an
expression:
Type conversion (done implicitly)
Cast expressions (done explicitly)
• Examples of implicit conversion:
float x;
int i;
if (x < i) ... /* Example 1 (operand)*/
x = i; /* Example 2 (assignment) */
In each case, i is implicitly converted to float type.
The Usual Arithmetic Conversions
• The usual arithmetic conversions are applied to
operands in an arithmetic or logical expression.
Operands are converted to the “smallest” type that will
safely accommodate both values.
• This is often done by converting (promoting) the operand
of the “smaller” type to the type of the other operand.
• Integral promotion
The Usual Arithmetic Conversions
• Examples of the usual arithmetic conversions:
char c;
short int s;
int i;
unsigned int u;
long int l;
unsigned long int ul;
float f;
double d;
long double ld;
i = i +
i = i +
u = u +
l = l +
ul = ul
f = f +
d = d +
ld = ld
c;
s;
i;
u;
+ l;
ul;
f;
+ d;
/*
/*
/*
/*
/*
/*
/*
/*
c is converted to int
*/
s is converted to int
*/
i is converted to unsigned int
*/
u is converted to long int
*/
l is converted to unsigned long int */
ul is converted to float
*/
f is converted to double
*/
d is converted to long double
*/
Conversion During Assignment
• The usual arithmetic conversions do not apply to
assignment. Instead, the value on the right side of the
assignment is converted to the type of the variable on
the left side.
• Warning: Converting from a “large” type to a “small” type
may not always produce a meaningful result:
int i;
float f;
i = f;
This assignment is meaningful only if the value of f—when
converted to an integer—lies between the smallest and largest
values allowed for an int variable. If f is too large or too small, i
will be assigned an apparently meaningless number.
Conversion During Assignment
• The conversion of a floating-point number to an integer
is done by dropping the fractional part of the number (not
by rounding to the nearest integer):
int i;
i = 842.97; /* i is now 842 */
i = -842.97; /* i is now -842 */
char c;
int i;
float f;
double d;
i = c;
f = i;
d = f;
/* c is converted to int
*/
/* i is converted to float */
/* f is converted to double */
c = 10000;
i = 1.0e20;
f = 1.0e100;
/*** WRONG ***/
/*** WRONG ***/
/*** WRONG ***/
Casting
• Casting is used for explicit type conversion.
• A cast expression has the form
( type-name ) expression
• Example 1:
float f = 3.5, frac_part;
frac_part = f - (int) f; /* frac_part is now 0.5 */
• Example 2:
int i = 5, j = 2;
float f;
f = i/j; /* f is now 2.0 */
f = ((float) i)/j; /* f is now 2.5 */
Avoiding overflow
• Casts are sometimes necessary to avoid overflow:
long i;
int j = 1000;
i = j * j;
/* overflow may occur */
• Using a cast avoids the problem:
i = (long) j * j;
• The statement
i = (long) (j * j);
/*** WRONG ***/
wouldn’t work, since the overflow would already have occurred by
the time of the cast.
The sizeof Operator
• The sizeof operator can be used to determine how much
memory a particular type requires:
printf("Size of char: %lu\n", (unsigned long)
sizeof(char));
printf("Size of int: %lu\n", (unsigned long)
sizeof(int));
printf("Size of long int: %lu\n", (unsigned long)
sizeof(long));
sizeof returns its answer in bytes.
• sizeof returns an implementation-defined unsigned
integer type. As a result, it is best to cast the value
returned by sizeof to unsigned long when trying to
print it.
The sizeof Operator
• sizeof works with variables as well as types:
int i;
printf("Size of i: %lu\n", (unsigned long)
sizeof(i));
Type Definitions
• Type definitions create new names for types:
typedef float Dollars;
typedef int Bool;
A common convention is to capitalize the first letter of a typedef
name.
• Once a type has been defined, it can be used in the same
way as the built-in type names:
Dollars cash_in, cash_out;
Bool flag;
• Advantages of type definitions:
Can make programs more understandable.
Can make programs easier to modify.
Can make programs more portable.
© Copyright 2026 Paperzz