Skip to content
Informatics

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, where printf lives.
  • main is the function where execution starts. It returns an int: 0 tells the operating system that all went well.
  • Braces delimit a block; each statement ends with a semicolon.
  • \n in 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.

TypeTypical sizeContent
char1 bytecharacter or small integer
int4 bytes (2 on some microcontrollers)signed integer
long long8 byteslarge signed integer
float4 bytesfloating point, about 7 digits
double8 bytesfloating 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 / 2 is 3, 7 % 2 is 1. To get 3.5 at least one operand must be real: 7.0 / 2.
  • Assignment: =, and the shorthand forms +=, -=, *=; i++ increases i by 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 use bool, true and false).
  • Logical: && (and), || (or), ! (not). They “short-circuit”: in b != 0 && a / b > 2 the division is not performed if b is 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.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
0
Would love your thoughts, please comment.x
()
x