Lesson 02: Fundamentals

Welcome to the second lesson in Programming in C. In this lesson, you will learn about variables, data types, constants, and literals, which are fundamental concepts for writing C programs.

Objectives

By the end of this lesson, you should be able to:

  • Understand and declare variables in C.
  • Identify and use various data types in C.
  • Define and use constants in C.
  • Differentiate and use various literals, including integers, floating-point numbers, characters, and strings.

Data Types

Data types specify the type of data that a variable can hold. In C, the data type of a variable determines the amount of memory allocated for it and the type of operations that can be performed on it.

Basic Data Types

  • int: Used for integer values.
    • Typical size: 4 bytes
    • Format specifier: %d
  • float: Used for single-precision floating-point values.
    • Typical size: 4 bytes
    • Format specifier: %f
  • double: Used for double-precision floating-point values.
    • Typical size: 8 bytes
    • Format specifier: %lf
  • char: Used for single characters.
    • Typical size: 1 byte
    • Format specifier: %c
int age = 25; 
float salary = 50000.50; 
double large_number = 123456789.123456789; 
char initial = 'A'; 
 
printf("age = %d\n", age); 
printf("salary = %f\n", salary); 
printf("large_number = %lf\n", large_number); 
printf("initial = %c\n", initial); 

Extended Data Types

  • short int: Used for smaller integer values.
    • Typical size: 2 bytes
    • Format specifier: %hd
  • unsigned int: Used for non-negative integer values.
    • Typical size: at least 2 bytes, usually 4 bytes
    • Format specifier: %u
  • long int: Used for larger integer values.
    • Typical size: at least 4 bytes, usually 8 bytes
    • Format specifier: %ld, %li
  • long long int: Used for even larger integer values.
    • Typical size: at least 8 bytes
    • Format specifier: %lld, %lli
  • unsigned long int: Used for non-negative large integer values.
    • Typical size: at least 4 bytes, usually 8 bytes
    • Format specifier: %lu
  • unsigned long long int: Used for very large non-negative integer values.
    • Typical size: at least 8 bytes
    • Format specifier: %llu
  • signed char: Used for small integer values, typically from -128 to 127.
    • Typical size: 1 byte
    • Format specifier: %hhd (integer value), %c (character)
  • unsigned char: Used for small non-negative integer values, typically from 0 to 255.
    • Typical size: 1 byte
    • Format specifier: %hhu (integer value), %c (character)
  • long double:
    • Typical size: 10 bytes, 12 bytes or 16 bytes
    • Format specifier: %Lf

Depending on which compiler you use and how it is configured, incorrect usage of signed and unsigned variables may trigger warnings or even errors.

/* valid usage */ 
unsigned int x = 42; 
signed int y = -42; 
 
/* invalid usage, but compilable */ 
unsigned int z = -42;   /* unsigned negative value */ 
 
printf("%u\n", x); /* this will print 42 */ 
printf("%d\n", y); /* this will print -42 */ 
printf("%u\n", z); /* this will NOT print -42, but 4294967254 */ 

Typedef: Creating Aliases

The typedef keyword allows you to create new names (aliases) for existing data types, but does not (usually) create a new type. This can make your code more readable and easier to manage.

typedef unsigned long ulong; 
ulong distance = 1000000; 

In this example, ulong is an alias for unsigned long, making the code more concise and easier to read.

A typedef may be used to simplify declarations of objects such as struct, union, or pointer types. Enums, structs and unions will be explained in later lessons, but here’s a quick example:

typedef enum { 
    RED, 
    GREEN, 
    BLUE 
} Color; 
 
typedef struct { 
    int x; 
    int y; 
} Point; 

In this example, Color is an alias for an enumeration of color values, and Point is an alias for a structure representing a point in a 2D space. As such, Color and Point can now be used as data types for specifying variables:

Color favorite_color = RED; 
Point point_a = {10, 20}; 

Literals

Literals represent fixed values used directly in the code. They can be of different types, including integers, floating-point numbers, characters, and strings. Unlike variables, literals cannot change and are hard-coded into the program.

Integer Literals

Integer literals are whole numbers without a decimal point. They can, depending on the compiler, be specified in decimal (base 10), octal (base 8), hexadecimal (base 16), or binary (base 2) formats.

int decimal = 10;   /* Decimal (base 10) */ 
int octal = 012;    /* Octal (base 8) */ 
int hex = 0xA;      /* Hexadecimal (base 16) */ 
int bin = 0b0101;   /* Binary (base 2) */ 

Floating-Point Literals

Floating-point literals represent numbers with a fractional part. They can be written with or without an exponent.

float f = 3.14f;     /* Single-precision floating-point */ 
double d = 3.14;     /* Double-precision floating-point */ 
float sf = 1.23e5;   /* using exponent: 1.23 * 10^5 */ 
double sd = 4.56e-2; /* using exponent: 4.56 * 10^-2 */ 

Character Literals

Character literals are enclosed in single quotes and represent a single character. They can also represent ASCII values.

char letter = 'A'; 
char newline = '\n'; /* Escape sequence for new line */ 

String Literals

String literals are enclosed in double quotes and represent a sequence of characters. They are stored as arrays of characters terminated with a null character ( ). The format specifier for string literals is %s.

char greeting[] = "Hello, World!"; 
char *multiline_str = "This is a multi-line\n"     /* using a pointer */ 
                      "string literal\n" 
                      "in C."; 
const char *str = R"( 
   This is a raw string literal. 
   It can contain multiple lines and special characters like \t and \n. 
   No need to escape quotes ("), backslashes (\), or other characters.)"; 

It is important to note that raw string literals (R"...") are not standard in C (up to C11). They are a feature introduced in C++11 and later versions of C++. Depending on your compiler, raw string literals could be undefined. You can also use different delimiters in raw string literals R"delim(...delim) as long as delim does not appear in the raw_characters section.

Escape Sequences

Escape sequences are used to represent special characters within string and character literals, that otherwise have specific functions. They start with a backslash (\).

  • \a: Alert (bell) character
  • \b: Backspace
  • \e: Escape character
  • \f: Form feed
  • \n: Newline
  • \r: Return
  • \t: Horizontal tab
  • \v: Vertical tab
  • \\: Backslash
  • \': Single quote
  • \": Double quote
  • \?: Question mark
  • \0: Null character
  • \nnn: Octal representation, represents the character with the ASCII code specified by up to three octal digits nnn.
  • \xhh: Hexadecimal representation, represents the character with the ASCII code specified by exactly two hexadecimal digits hh.
  • \uxxxxxxxx: Universal character name in hexadecimal notation (C99 and later), represents a Unicode character specified by the hexadecimal number xxxxxxxx.
  • \u{xxxx}: Universal character name in hexadecimal notation (C11 and later), represents a Unicode character specified by the Unicode code point in {xxxx}.
#include <stdio.h> 
 
int main() { 
    printf("Horizontal tab: \t\n"); 
    printf("Escape character: \e\n"); 
    printf("Escape character (hex): \x1b\n"); 
    printf("Greek capital letter Omega: \u03A9\n"); 
    printf("Unicode smiley face emoji: \u0001F600\n"); 
    return 0; 
} 

Variables

Variables are used to store data that can be manipulated by a program. Each variable in C must be declared with a specific data type before it can be used. Variables can hold different types of data such as integers, floating-point numbers, characters, etc.

Declaring Variables

To declare a variable, specify the data type followed by the variable name:

int age; 
float salary; 
char initial; 

Initializing Variables

Variables can be initialized at the time of declaration. The value assigned to the variable at the time of declaration is known as the literal, which is always placed on the right side of the equal sign.

int age = 25; 
float salary = 50000.50; 
char initial = 'A'; 

In this case, 25, 50000.50, and 'A' are literals, while age, salary, and initial are the variables. Variables can change values during the execution of a program, whereas literals are fixed values. Previously declared and/or initialized variables can have new values assigned to them. This is not an initialization but rather a reassignment or update of the variable’s value. A new literal is then assigned to the variable.

int age = 25;  /* correct: variable declaration and initialization */ 
age = 35;      /* correct: variable assignment */ 
45 = age;      /* incorrect */ 
24 = 42;       /* incorrect */ 
  • int age = 25; is both a declaration and an initialization of the variable age.
  • age = 35; is an assignment or rather reassignment of the variable age with a new literal 35.
  • 45 = age; is an incorrect assignment. Literals (like 45) cannot be on the left-hand side of an assignment because they are fixed values.
  • 24 = 42; Both 24 and 42 are literals, and neither can be assigned to the other. Literals cannot be on the left-hand side of an assignment because they represent fixed values.

Using Variables

Variables can be used in expressions, passed as arguments to functions, and manipulated in various ways. This is just a simple example:

int age = 35; 
int years = 5; 
int total_age = age + years; /* Using variables in an expression */ 
printf("Total Age: %d\n", total_age); /* Output the result: 'Total age: 40' */ 

Constants

Constants are values that, much like literals, cannot be changed once assigned. They are, similarly to variables, declared but using the const keyword. Constants are useful for defining fixed values that should not be altered during program execution.

Declaring Constants

const int DAYS_IN_WEEK = 7; 
const float PI = 3.14159; 
const char NEWLINE = '\n'; 

C also allows for macros to be used for declaring constant values for the compiler. Macros will be covered in a later lesson.

Using Constants

Constants are used in the same way as variables but cannot be modified after their initial assignment:

printf("There are %d days in a week.\n", DAYS_IN_WEEK); 
printf("The value of PI is approximately %.5f\n", PI); 

Exercises

  1. Declare and Initialize Variables: Create variables of different types and initialize them with appropriate values.
  2. Using Constants: Declare constants for the number of days in a week and the value of Pi. Use them in appropriate print statements. Try using a macro with #define.
  3. Understanding Literals: Write a program that demonstrates the use of integer, floating-point, character, and string literals. Use printf(...); in your demonstration.
  4. ’Deux et deux font cinq’: The statement ’Deux et deux font cinq’ (’Two and two make five’) represents a mathematical falsehood, often cited as a simple example of a logical error that contradicts basic arithmetic principles. This phrase has been used in various contexts, notably in George Orwell’s novel ’Nineteen Eighty-Four,’ where it symbolizes the distortion of truth and the power of propaganda.

    While inherently untrue in standard arithmetic, ’Deux et deux font cinq’ has also sparked artistic and philosophical explorations. It predates Orwell’s novel, appearing in works such as Alphonse Allais’ absurdist short stories and Vadim Shershenevich’s imagist art manifesto, where it challenges conventional thinking and invites reflection on the limits of rationality.

    In this exercise, you will explore the concept of ’Deux et deux font cinq’ through the lens of programming with C. By examining how data types, operations sequence, and variable manipulations can affect computational outcomes, the aim is to illustrate the precision required in programming logic and highlight the implications of deviating from mathematical norms.

    Rewrite the following program so that it prints mathematically correct statements.

    #include <stdio.h> 
     
    int main() { 
        int i5 = 5; 
        int i4 = 4; 
     
        printf("%d / %d = %d0, i5, i4, i5 / i4);                       /* 5 / 4     = 1.25 (?) */ 
        printf("%d * %d = %d0, i5 / i4, 2, i5 / i4 * 2);               /* 1.25 * 2  = 2.5  (?) */ 
        printf("%d + %d = %d0, i5 / i4 * 2, i5 / i4 * 2, i5);          /* 2.5 + 2.5 = 5    (?) */ 
        printf("Deux et deux font cinq!0); 
     
        return 0; 
    } 
    

Solutions

Example solution to ’Declare and Initialize Variables’:

#include <stdio.h> 
 
int main() { 
    int age = 25; 
    float height = 5.9; 
    char initial = 'A'; 
 
    printf("Age: %d0, age); 
    printf("Height: %.1f0, height); 
    printf("Initial: %c0, initial); 
 
    return 0; 
} 

Example solution to ’Using Constants’:

#include <stdio.h> 
 
#define PI 3.14159 
 
int main() { 
    const int DAYS_IN_WEEK = 7; 
 
    printf("There are %d days in a week.0, DAYS_IN_WEEK); 
    printf("The value of PI is approximately %.5f0, PI); 
 
    return 0; 
} 

Example solution to ’Understanding Literals’:

#include <stdio.h> 
 
int main() { 
    int decimal = 10; 
    float pi = 3.14f; 
    char letter = 'A'; 
    char greeting[] = "Hello, World!"; 
 
    printf("Integer literal: %d0, decimal); 
    printf("Floating-point literal: %.2f0, pi); 
    printf("Character literal: %c0, letter); 
    printf("String literal: %s0, greeting); 
 
    return 0; 
} 

Example solution to ’Deux et deux font cinq’:

#include <stdio.h> 
 
int main() { 
    float f5 = 5; 
    float f4 = 4; 
 
    printf("%0.0f / %0.0f = %0.2f0, f5, f4, f5 / f4); 
    printf("%0.2f * %d = %0.1f0, f5 / f4, 2, f5 / f4 * 2); 
    printf("%0.1f + %0.1f = %0.0f0, f5 / f4 * 2, f5 / f4 * 2, f5); 
 
    return 0; 
} 

Next Lesson

In the next lesson, we will delve deeper into Input/Output (I/O) operations in C. We will cover techniques for handling input from users and files, using functions like printf, scanf, fprintf, and fscanf. This knowledge will enable you to create programs that interact with users and manage data through file operations.

Next Lesson