The C language: first program, types, variables, operators, input and output
Structure of a C program and compilation, types and variables, arithmetic, logical and comparison operators, conversions, printf and scanf with a resistor example.
C, created by Dennis Ritchie at Bell Labs between 1969 and 1973 to write the Unix operating system, is still the language of operating systems, drivers, firmware and almost every microcontroller. It is small, fast and close to the hardware, and for exactly that reason it demands discipline: the compiler checks little and leaves memory in the programmer’s hands. In this lesson we write the first programs: structure, types, variables, operators, input and output.
The first program
#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return 0;
}
#include <stdio.h>asks the preprocessor to include the declarations of the standard input/output library, whereprintflives.mainis the function where execution starts. It returns anint: 0 tells the operating system that all went well.- Braces delimit a block; each statement ends with a semicolon.
\nin the string is the newline character.
Compile and run with gcc hello.c -o hello and ./hello. Always turn on warnings, gcc -Wall -Wextra: many C errors are reported only as warnings.
Types and variables
Every variable has a type, which sets how many bytes it takes and how its bits are interpreted, and must be declared before use.
| Type | Typical size | Content |
|---|---|---|
char | 1 byte | character or small integer |
int | 4 bytes (2 on some microcontrollers) | signed integer |
long long | 8 bytes | large signed integer |
float | 4 bytes | floating point, about 7 digits |
double | 8 bytes | floating point, about 16 digits |
unsigned gives the unsigned versions. sizeof(type) tells how many bytes a type takes on that system.
int n = 10; /* declaration with initialisation */
double v = 3.3;
char c = 'A'; /* in single quotes: a character, that is the number 65 */
const double PI = 3.14159265358979; /* constant: cannot be modified */
Careful: an uninitialised local variable holds a random value, whatever was in that memory before. Using it before assigning a value is an error the compiler does not always report.
Operators
- Arithmetic:
+ - * /and%(remainder). Between integers division truncates:7 / 2is 3,7 % 2is 1. To get 3.5 at least one operand must be real:7.0 / 2. - Assignment:
=, and the shorthand forms+=,-=,*=;i++increasesiby one. - Comparison:
== != < > <= >=. They give 1 (true) or 0 (false): C has no built-in boolean type, and any non-zero value is true (with<stdbool.h>you can usebool,trueandfalse). - Logical:
&&(and),||(or),!(not). They “short-circuit”: inb != 0 && a / b > 2the division is not performed ifbis zero.
The classic mistake is writing if (x = 5) instead of if (x == 5): the first assigns 5 to x and the condition is always true. With -Wall the compiler warns.
Conversions. In an expression with different types, the “smaller” type is converted to the “larger” one: in n * 2.5 the integer n becomes a double. Assigning a real to an integer drops the fractional part: int k = 3.9; is 3. You can convert explicitly with a cast: (double)sum / n.
Input and output
printf prints with a format, in which % specifiers mark where and how to insert values: %d integer, %u unsigned, %f real, %c character, %s string, %x hexadecimal. %.2f prints two decimals, %5d takes at least five characters.
scanf reads from the keyboard with the same format, but it needs the variable’s address, obtained with & (we will see why in the lesson on pointers):
#include <stdio.h>
int main(void)
{
double r1, r2;
printf("Values of the two resistors in ohms: ");
if (scanf("%lf %lf", &r1, &r2) != 2) { /* scanf returns how many values it read */
printf("Invalid input\n");
return 1;
}
double series = r1 + r2;
double parallel = r1 * r2 / (r1 + r2);
printf("Series: %.1f ohm, parallel: %.1f ohm\n", series, parallel);
return 0;
}
With 1000 and 2200 the program prints “Series: 3200.0 ohm, parallel: 687.5 ohm”. Note %lf to read a double with scanf, while printf needs only %f, and the check on the value scanf returns: a robust program never trusts its input.
Style matters
A program is written once and read many times, often by someone else. Variable names that say what they hold (voltage_mV rather than x), consistent indentation, comments that explain why and not what, short functions. The compiler ignores all this; whoever has to fix a bug at two in the morning does not.




