type name |
size |
encoding |
precision |
min value |
max value |
bool |
1 bit** |
0:false 1:true |
exact integer |
0 |
1 |
char |
8 bits |
signed integer*** |
exact integer |
-128 |
127 |
unsigned char |
8 bits |
unsigned integer |
exact integer |
0 |
255 |
short |
16 bits |
signed integer |
exact integer |
-32768 |
32767 |
unsigned short |
16 bits |
unsigned integer |
exact integer |
0 |
65535 |
int |
32 bits* |
signed integer |
exact integer |
-2.1 billion* |
2.1 billion* |
unsigned int |
32 bits* |
unsigned integer |
exact integer |
0 |
4.3 billion* |
long |
64 bits* |
signed integer |
exact integer |
-9.2 x 1018* |
9.2 x 1018* |
unsigned long |
64 bits* |
unsigned integer |
exact integer |
0 |
1.8 x 1019* |
float |
32 bits |
floating point |
7 decimal digits |
-3.4 × 1038 |
3.4 × 1038 |
double |
64 bits |
floating point |
16 decimal digits |
-1.8 x 10308 |
1.8 x 10308 |
* Size and range for "int" and "long" assume 64-bit processors on the EWS lab machines. These types may have smaller size and range on 32-bit and 16-bit platforms (like the LC-3).
** While only one bit is required to store a bool type, the compiler will pad it to 1 byte (or the addressability of the machine)
*** Note that the "char" data type is more commonly used to store ASCII characters. In this case, you can consider the integer value to correspond to the ASCII character it represents.
type |
operator |
example |
size |
description |
pointer to Z |
* |
int * x; |
64 bits (8 bytes) § |
An object containing the address of some object with type Z |
array of nZs |
[] |
int x[4]; |
n x size of Z §§§ |
Contiguously allocated set of n objects with type Z §§§ |
structure |
struct |
struct { int x, y; } vector; |
Sum of the size of the members §§ |
Sequentially allocated set of member objects |
§ Assumes 64-bit processors on EWS lab machines.
§§ The compiler may pad structures with dummy elements, resulting in larger than expected sizes.
§§§ There is an exception for array declarations if they are function parameters. If an "array of Zs" is declared as a function parameter, it is immediately converted by the compiler to "pointer to Z". For example:
void foo(int x[4]);
is immediately converted by the compiler to:
void foo(int * x);
You can put suffixes on numbers that you put in your C code to make them have certain types. This is useful if you want to force an arithmetic expression to use floating point (fractional) math, for example. This does not change the type of a variable you assign to, however; variable types are fixed to the type you declare them with.
Suffix |
Example |
Resulting type |
ul |
42ul |
unsigned long |
u |
42u |
unsigned int |
l |
42l |
long |
(none) |
42 |
int |
.f |
42.0f |
float |
. |
42.0 |
double |
Literals are allocated in temporary (e.g. register) space, although the variables they are assigned to may not be.
Name |
Example |
Description |
Resulting types |
character |
'c' |
ASCII value for a particular character |
int |
string |
"hello" |
NUL terminated array of ASCII values (string) |
char * |
Note that the string literal is special in that it implicitly allocates and initializes space for the array of chars in a static memory region. The string pointer and character literal are allocated in temporary space.
There is one exception to this, which is if a string literal is used as a char array initializer, i.e.:
char string[6] = "hello";
In this case, the string is stored in temporary space and used to initialize the array. The following is equivalent:
char string[6] = { 'h', 'e', 'l', 'l', 'o', '\0' };
The following escape sequences are allowed in string and character literals:
Sequence |
Result |
\0 |
NUL |
\n |
newline |
These tables describe operators as they work in C expressions. (i.e. not variable declarations)
operator |
syntax |
type of x |
resulting type |
description |
dereferencing |
*X |
pointer to T |
T |
access what X points to |
referencing |
&X |
T |
pointer to T |
create a pointer to X by calculating its address |
sizing |
sizeof(X) |
any |
int |
calculate size of the given object or type in bytes |
operator |
syntax |
type of X |
type of Y |
resulting type |
description |
pointer addition |
X + Y |
pointer to T |
integer |
pointer to T |
add Y * sizeof(T) to address in X |
pointer subtraction |
X - Y |
pointer to T |
integer |
pointer to T |
subtract Y * sizeof(T) from address in X |
indexing |
X[Y] |
pointer to T or array of T § |
integer |
T |
given base pointer, access element Y of array |
indirect member access |
X->Y |
pointer to struct |
member identifier |
type of member Y |
equivalent to (*X).Y |
member access |
X.Y |
struct |
member identifier |
type of member Y |
access member Y of X |
§ Technically, the indexing operator only operates on pointers since arrays are converted to pointers to their first element when used in an expression.
specifier |
format description |
printf type |
scanf type |
%c |
ASCII character |
char |
char * |
%d |
signed decimal integer |
int |
int * |
%f |
decimal with fractional part |
float |
float * |
%hd |
signed decimal integer |
short |
short * |
%hhd |
signed decimal integer |
char |
char * |
%hhu |
unsigned decimal integer |
unsigned char |
unsigned char * |
%hhx |
hexadecimal |
unsigned char |
unsigned char * |
%hu |
unsigned decimal integer |
unsigned short |
unsigned short * |
%hx |
hexadecimal |
unsigned short |
unsigned short * |
%ld |
signed decimal integer |
long |
long * |
%lf |
decimal with fractional part |
double |
double * |
%lu |
unsigned decimal integer |
unsigned long |
unsigned long * |
%lx |
hexadecimal |
unsigned long |
unsigned long * |
%p |
hexadecimal address |
T * |
T ** |
%s |
ASCII string |
char * |
char * |
%u |
unsigned decimal integer |
unsigned int |
unsigned int * |
%x |
hexadecimal |
unsigned int |
unsigned int * |
For the %c
specifier, note that scanf will match any character include a space or newline. To make the %c
specifier search for a non-whitespace character, which is usually what you want, you need to put a space before it in the format string, i.e:
scanf(" %c", &character);
For the %s
specifier, printf
takes a NUL terminated array of characters (C string) and outputs all the characters. Scanf
scans for the next "word" (sequence of non-whitespace characters), takes an array of characters, and overwrites the array with the C string corresponding to the input word. The array must be large enough to hold the word and the NUL terminator.
For the %p
specifier, T is any C type.