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.

Primitive data types

Integer types

Type Size Sign
char 8 bits -/0/+ or 0/+
unsigned char 8 bits 0/+
signed char 8 bits -/0/+
int 16 or 32 bits -/0/+
unsigned int 16 or 32 bits 0/+
short 16 bits -/0/+
unsigned short 16 bits 0/+
long 64 bits -/0/+
unsigned long 64 bits 0/+

Floating point types

Type Size Precision
float 32 bits 6 decimal places
double 64 bits 15 decimal places
long double 80 bits 19 decimal places

void type

The void type specifies that no value is available. Used as:

  • void function return
  • void function argument
  • void pointer

Type casting

Convert one data type to another.

(type_name) expression

Derived & user defined data types

Derived data types add functionality and relationships to primitive data types.

  • Arrays
  • Structures
  • Unions
  • Functions
  • Pointers

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.

struct person {
  string name;
  string number;
};

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.

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!";

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;

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.

C Standard library