A constant is a fixed value written directly in the code; a variable is a name associated with a memory location whose content can change. The type chosen for each determines how much space it occupies, what values it can hold, and what operations can be applied to it.
1Lab objectives
- Writing integer constants in bases 10, 8, and 16, and using the
UandLsuffixes - Using real, character, and string constants, including escape sequences
- Declaring variables with the type suited to the range of values
- Experimentally determining sizes with the
sizeofoperator - Telling scope apart from a variable's lifetime
2Constants
Literal constants are fixed values that cannot be changed during execution. Their type is determined automatically by the compiler, based on the value and the syntax used.
Integer constants
| Base | Writing convention | Examples |
|---|---|---|
| Decimal (10) | the first digit is not 0 | 23, -555L, 3276L |
| Octal (8) | the first digit is 0; the digits 8 and 9 are illegal | 067, -067, 067u |
| Hexadecimal (16) | prefix 0x or 0X | 0x1F, 0xFFu, 0xAB3L |
int x = 010; does not mean ten, it means eight - the 0 prefix
triggers interpretation in base 8. This is a frequent mistake when writing calendar dates or
codes with insignificant leading zeros.Default type determination
| Situation | Assigned type | Example |
|---|---|---|
the value fits in the int range | int | 15, 23 |
exceeds int, fits in long | long | 99999 |
exceeds long | double | 98765432100 |
The default type can be forced with suffixes: U/u for
unsigned, L/l for long, combined as
UL.
Character constants and escape sequences
| Sequence | Meaning | ASCII code |
|---|---|---|
'\n' | newline | 10 |
'\t' | horizontal tab | 9 |
'\r' | carriage return | 13 |
'\0' | null character - marks the end of a string | 0 |
'\\' | backslash | 92 |
'\'' | apostrophe | 39 |
'A' is a character constant and
occupies 1 byte. "A" is a string and occupies 2 bytes: the letter
plus the '\0' terminator. Confusing the two produces errors that are hard to
track down.3Fundamental data types
| Type | Typical size | Range of values | printf specifier |
|---|---|---|---|
char | 1 byte | −128 ... 127 | %c / %d |
unsigned char | 1 byte | 0 ... 255 | %u |
short | 2 bytes | −32,768 ... 32,767 | %hd |
int | 4 bytes | −2,147,483,648 ... 2,147,483,647 | %d |
unsigned int | 4 bytes | 0 ... 4,294,967,295 | %u |
long long | 8 bytes | ±9.2 · 10¹⁸ | %lld |
float | 4 bytes | ±3.4 · 10³⁸, ~7 significant digits | %f |
double | 8 bytes | ±1.7 · 10³⁰⁸, ~15 significant digits | %lf |
bool (C++) | 1 byte | true / false | - |
char ≤ short ≤ int ≤ long). On an 8-bit
microcontroller, int is 2 bytes; on an ordinary PC, 4. That is why you always
check with sizeof.4Variables
Declaring a variable reserves space in memory and associates it with a name and a type:
type name; // simple declaration, undefined value type name = value; // declaration with initialization type n1, n2, n3; // several variables of the same type const type name = value; // a value that can no longer be changed
5Scope and lifetime
| Class | Where it is visible | How long it lives | Default initial value |
|---|---|---|---|
auto (local) | in the block where it is declared | until the block exits | undefined |
local static | in the block where it is declared | the entire program execution | 0 |
| global | throughout the file, after the declaration | the entire program execution | 0 |
extern | in other source files | the entire program execution | 0 |
register | in the block where it is declared | until the block exits | undefined |
static variable is only
visible in its own function, but is not destroyed on exit: on the next call it finds its
value again. This is the standard mechanism for counters that must remember their state
between calls.6Execution simulator
Watch step by step how an ordinary local variable behaves compared to one
declared static, over three successive calls of the same function.
7Source code
#include <stdio.h>
#include <limits.h>
int main(void)
{
printf("Type Bytes Min Max\n");
printf("-------------------------------------------------------\n");
printf("char %2zu %-18d %d\n", sizeof(char), CHAR_MIN, CHAR_MAX);
printf("short %2zu %-18d %d\n", sizeof(short), SHRT_MIN, SHRT_MAX);
printf("int %2zu %-18d %d\n", sizeof(int), INT_MIN, INT_MAX);
printf("long %2zu %-18ld %ld\n", sizeof(long), LONG_MIN, LONG_MAX);
printf("float %2zu\n", sizeof(float));
printf("double %2zu\n", sizeof(double));
return 0;
}
#include <stdio.h>
int main(void)
{
int decimal = 100; // base 10
int octal = 0144; // base 8 -> also 100
int hexadecimal = 0x64; // base 16 -> also 100
printf("%d %d %d\n", decimal, octal, hexadecimal); // 100 100 100
// the same value shown in different bases
printf("decimal: %d octal: %o hex: %X\n", 255, 255, 255);
// the leading-zero trap
int wrong = 010;
printf("010 means %d, not 10!\n", wrong); // 8
// character vs string
char c = 'A';
char s[] = "A";
printf("sizeof('A') in C = %zu, sizeof(\"A\") = %zu\n", sizeof(c), sizeof(s));
return 0;
}
#include <stdio.h>
int main(void)
{
short small = 32767; // the maximum value for short
printf("before: %d\n", small);
small = small + 1; // overflow!
printf("after +1: %d\n", small); // -32768, drops to the minimum value
unsigned char u = 255;
u = u + 1;
printf("unsigned char 255+1 = %u\n", u); // 0, wraps back to the start
return 0;
}
8Code workshop
The sizes of types and their overflow behavior are not learned from tables, but by seeing them. Run the programs below and change the values to see exactly where each type breaks.
9Work tasks
- Run the size-checking program and note down the values obtained on the lab computer.
- Write the value 200 in bases 10, 8, and 16 and check that the printed result is identical.
- Declare a
shortvariable with the maximum value and add 1; explain the result. - Compare
sizeof('A')in C withsizeof('A')in C++ - the results differ, explain why. - Write a function with a
staticcounter and call it five times; print the value on each call. - Declare an uninitialized local variable, print it, and run the program three times - see whether the value changes.
- Use all the escape sequences from the table in a single
printfand observe the effect.
10Extended application
<limits.h>, the maximum value of the int type on your
computer: start from 1 and double the value until it becomes negative, then adjust. Compare the
result with INT_MAX. Repeat for unsigned int.