C (programming language)

C is a general-purpose, procedural programming language. It was designed to be compiled to provide low-level access to memory and language constructs that map efficiently to machine instructions.

Program structure

  • preprocessor command
  • functions
  • variables
  • statements & expressions
#include <stdio.h>

int main(void) {
  printf("hello, world! \n");
}

Command-line arguments

int main(int argc, char* argv[])
  • int argc - argument count
  • char* argv[] or string argv[] (with helper) - argument vector

The first typed argument is argv[1] not argv[0] which is always the program's name.

Return value

Declare type int to return exit codes.

Compile and execute

Human readable source code needs to be compiled to machine code using a compiler like gcc or clang.

From the command line, run clang <filename>.c to generate a.out executable file; then ./a.out to execute the program. Including the -o flag writes output to file:

clang -o hello hello.c

The make utility utilizes structured information contained in a makefile in order to properly compile and link a program.

Data types

Integer types

  • char = 8 bits -/0/+ or 0/+
    • unsigned 0/+
    • signed -/0/+
  • int = 32 bits -/0/+
    • unsigned = 32 bits 0/+
    • short = 16 bits -/0/+
    • unsigned short = 16 bits 0/+
    • long = 64 bits -/0/+
    • unsigned long = 64 bits 0/+

Floating point types

  • float - 32 bits precise to 6 decimal places
  • double - 64 bits precise to 15 decimal places
  • long double - 80 bits precise to 19 decimal places

Return type

  • void

Strings

There is no such type as string. A string is implemented as a pointer to the first character in a sequence of characters requiring explicit termination. char* s is equal to string s where typedef char* string is the helper definition resulting in the latter. Since every string ends with a null terminating character, it is sufficient to point to the first address of a string in a pointer.

A string is an array of chars. The null character is a control character with the value zero. \0—literally 00000000—terminates the end of a string, and therefore the memory requirements for a null-terminated string is the number of bytes required by the total number of characters plus one byte for the null character.

char* string;

// Helper
typedef char* string;

// Helper usage
string s = "Hello, world!";

Arrays

Data container that can store a sequential collections of elements of the same type. The name of an array is a pointer to the first item in the array.

Declare an array by specifying the type and number of elements required.

data_type array_name[array_size];

Example declaration:

int scores[4]

There are two ways to initialize an array. All array elements that are not initialized explicitly are zero-initialized.

  1. Static array initialization - Initializes all elements of array during its declaration.
// The number of values cannot exceed the
// number declared in square brackets
int scores[4] = { 90, 96, 89, 94 };

// Omitting the size creates an array big enough
// to hold only the number of initialized values
int scores[] = { 90, 96, 89, 94 };
  1. Dynamic array initialization - The declared array is initialized some time later during execution of program.
int scores[4]
scores[0] = 90;
scores[1] = 96;
sores[2] = 96;
scores[3] = 96;

Access array elements by index number.

scores[0] // 90

Structures

Data container that can store data items of differing types.

typedef struct {
  string name;
  string number;
} Person;

Casting

Convert one data type to another.

Operators

Arithmetic

  • add +
  • subtract -
  • multiply *
  • divide /
  • modulus %
  • increment ++
  • decrement --

Logical

  • logical AND &&
  • logical OR ||
  • logical NOT !

Relational

  • equality ==
  • inequality !=
  • less than <
  • greater than >
  • less than or equal to <=
  • greater than or equal to >=

Bitwise

  • binary AND &
  • binary OR |
  • binary XOR ^
  • binary one's compliment ~
  • binary left shift <<
  • binary right shift >>

Assignment

  • simple assignment =
  • add AND assignment +=
  • subtract AND assignment -=
  • multiply AND assignment *=
  • multiply AND assignment /=
  • modulus AND assignment %=
  • left shift AND assignment <<=
  • right shift AND assignment >>=
  • bitwise AND assignment &=
  • bitwise exclusive OR assignment ^=
  • bitwise inclusive OR assignment |=

Conditional statements

// if/else
if (boolean-expression) {
  // code executed if bool-exp evaluates to true
} else {
  // code executed if bool-exp evaluates to false
}

// switch
int x = 2;
switch(x) {
  case 1:
    // code executed if case evaluates to true
    break;
  case 2:
    // code executed if case evaluates to true
    break;
  default:
    // code executed if no prior break occurs
}

// ternary operator
int x = (expr) ? 5 : 6; // 5 if `expr` evaluates to true, else, 6

Loops

  • while - repeats while expression evaluates to true
  • do while - repeats once then checks the expression (guaranteed to run at least once)
  • for - repeats a specified number of times

Variables

Variable definition says where the variable gets stored. i.e. where and how much storage to create for the variable.

type variable_list;

Variable declaration gives details about the properties of a variable. Though you can declare a variable multiple times in your C program, it can be defined only once in a file, a function, or a block of code.

extern type variable_list;

Scope

Local variables can only be accessed within the functions in which they are created. They are passed by value in function calls, meaning only a copy of the variable's value is passed and not the variable itself.

Global variables can be accessed by any function in the program.

Functions

A function declaration tells the compiler about a function name and how to call the function. The actual body of the function can be defined separately.

return_type function_name( parameter_list );

Function definition:

return_type function_name( argument_list ) {
   body of the function
}

To call a function, pass the required parameters along with the function name.

function_name( argument_list );

Pointers

A pointer is a variable whose value is the address (location in memory) of another variable. The type describes the data located at that memory address.

  • & - "address of" operator
  • * - before a variable declaration is a "pointer to" operator
  • * - before a variable expression is a "go to address" operator

It is considered best practice to set uninitialized pointers to NULL.

Dereferencing

The dereference operator is also known as an indirection operator, which is represented by (*). When indirection operator is used with the pointer variable, then it is known as dereferencing a pointer. When we dereference a pointer, then the value of the variable pointed by this pointer will be returned.

  • It can be used to access or manipulate the data stored at the memory location, which is pointed by the pointer.
  • Any operation applied to the dereferenced pointer will directly affect the value of the variable that it points to.

Typedef

Typedef allows for assigning a name to existing or user defined data types.

// Existing
typedef char* string;

// User defined
typedef struct {
  string name;
  string number;
} Person;

C Standard library