Programming in C

Fast Track to C Syntax for Programmers

Gerald Senarclens de Grancy

Compiling a Basic Program

#include <stdio.h>

/* Hello World program written in C. */
int main(void) {
  printf("Hello, World!\n");  // output some text
  return 0;  // 0 means success
}

Download hello.c

Compilation can be done with either clang or gcc (part of the GNU Compiler Collection, GCC).

clang $INFILE -o $PROGRAM_NAME
gcc $INFILE -o $PROGRAM_NAME

I/O

Writing to Standard Output

#include <stdio.h>

/* Hello World program written in C. */
int main(void) {
  printf("Hello, World!\n");  // output some text
  return 0;  // 0 means success
}

Visualize execution

Reading Input

#include <stdio.h>

int main(void) {
  char line[20];
  int number = 0;  // safer to initialize values
  printf("Enter an integer between 1 and 6 (inclusive): ");
  fgets(line, sizeof(line), stdin);
  sscanf(line, "%d", &number);
  printf("You've entered the number %d.\n", number);
  return 0;
}

Download input.c

Variables and Data Types

#include <stdio.h>
#include <stdbool.h>

int main() {
  bool b1 = true, b2 = false;  // bool, true and false require <stdbool.h>
  char c1 = 'x', c2 = 115;  // 115 is the ASCII code for 's'
  int i = -5;
  unsigned int u = 210;
  long int l = 12345689;
  float f = 1.23;
  double d = 1.2345;
  printf("b1=%d b2=%d\n", b1, b2);
  printf("c1=%c c2=%c c2=%d\n", c1, c2, c2);
  printf("i=%d u=%u l=%ld\n", i, u, l);
  printf("f=%f d=%lf\n", f, d);
  return 0;
}

Visualize execution

Block Scope

Identifiers are only valid in their defining block

#include <stdio.h>

int main() {
  {
    int number = 3;
  }
  // printf("%d", number);  // error: number not declared in this scope
  return 0;
}

Download block_scope.c

Conditional Execution

if and else

if (expression) {
  // block
} else if (expression) {
  // block
} else {
  block
}

The ternary operator provides a shorthand

Type result = condition ? value_if_true : value_if_false;

Example: if and else

#include <stdio.h>

int main(void) {
  int guess = 3;  // entered by the user
  if (guess == 4) {  // guaranteed random guess, used a die
    printf("You won!\n");
  } else {
    printf("Better luck next time, loser!\n");
  }
  return 0;
}

Visualize execution

switch

The C switch statement jumps to the block of code matching the value of an expression.
It executes one or multiple code blocks among many alternatives.

switch (expression) ‚Äč{
    case constant1:
      // statements
      break;  // without break, execution of the following blocks continues
    case constant2:
      // statements
      break;
    // ...
    default:
      // statements
}

Example: switch

#include <stdio.h>
int main(int argc, char* argv[]) {
  switch (argc) {  // switch evaluates an expression: (argc)
  case 1:  // if the result of the expression evaluates to 1, jump here
    printf("Only the command was entered.\n");
    break;  // break - jump out of the 'switch' block to avoid falltrough
  case 2:
    printf("Command plus one argument.\n");
    break;
  case 3:
    printf("Command plus two arguments.\n");
    break;
  default:  // any other value of the expression jumps here
    printf("Command plus %d arguments.\n", argc-1); break;
  }
  return 0;
}

Visualize execution

while Loops

while (expression) {
  // block
}

do ... while: run code block at least once regardless of the expression

do {
  // block
} while (expression);

Example

#include <stdio.h>

int main(void) {
  int n = 10;
  while (n > 0) {  // execute block while expression evaluates to `true`
    printf("%d, ", n);
    --n;  // avoid side effects in statement above
  }
  printf("FIRE!\n");
  return 0;
}

Visualize execution

Example: Execute a block of code at least once

#include <stdio.h>

int main() {
  int condition = 0;
  do {
    printf("Do this at least once.\n");
  } while (condition);
  printf("FIRE!\n");
  return 0;
}

Visualize execution

for Loops

for (initialization; condition; update_statement) {
  // block
}

initialization and update_statement are optional

Every for loop can be expressed as while loop

// initialization
for (; condition; ) {
  // block
  // update_statement;
}

// initialization
while (condition) {
  // block
  // update_statement
}

Example

#include <stdio.h>

int main() {
  int user_input = 3;  // skipping actual input code
  for (int i = 0; i < user_input; ++i) {
    printf("counting up: %d\n", i);
  }
  for (int j = user_input; j >= 0; --j) {
    printf("counting down: %d\n", j);
  }
  for (int j = 0; j < 10; j += user_input) {
    printf("counting with step != 1: %d\n", j);
  }
  return 0;
}

Visualize execution

Function Signature

aka. type signature or type annotation

Defines the data types of the parameters and return value

For example, a function that returns the sum of two integers:

(int)(int, int)

Function Declaration

aka. function prototype or function interface

  • Specifies the function name and type signature, but omits the body
  • Required for using functions that are defined elsewhere
  • Promise to the compiler that the function will exist when linking

For example, a function that returns the sum of two integers:

int sum(int a, int b);

The parameter names are optional:

int sum(int, int);

Function Definition

  • Adds the function body to the declaration
  • The signature and name must exactly match the declaration
Type function_name(Type parameter1, Type parameter2, ...) { body }

For example, a function that returns the sum of two integers:

int sum(int a, int b) {
  return a + b;
}

Pass by Value

By default, C copies argument values to function parameters

#include <stdio.h>

void pass_by_value(int i) {
  i = 5;
  printf("i: %d (at the end of the called function)\n", i);
}

int main() {
   int i = 3;
   printf("i: %d\n", i);
   pass_by_value(i);
   printf("i: %d (after returning from function)\n", i);
   return 0;
}

Visualize execution

Questions
and feedback...