Type, Variable, Assignment, and Expression

Types

  • For each type, understand:

    • is a class type?

    • is numeric?

    • is ordered?

    • is signed?

    • is exact?

    • range

    • related types

Common C++ Types

Name

Tags

int

non-class, numeric, signed, ordered, exact

unsigned int

non-class, numeric, unsigned, ordered, exact

float

non-class, numeric, signed, ordered, not exact

double

non-class, numeric, signed, ordered, not exact

char

non-class, numeric, unsigned, ordered, exact

string

class, not numeric, ordered

vector

class template, not numeric

  • Derived types - Types that are derived from other data-types.

  • Class templates

    Class templates can be instantiated by specifying the template arguments to generate class types.

    • The template itself is not a type or class

    • E.g. vector is a template while vector<int> is a type

Variables

  • identifier naming

     1// ==== identifiers ====
     2
     3// ---- correct ----
     4int _a;
     5int ____;
     6int a10___;
     7int a_1_0;
     8int _1_0;
     9
    10// ---- wrong ----
    11int a$;
    12int 3x;
    13int mid-var;
    14
    15// ---- Good ----
    16int myVar1;  // var is a good abbreviation for variable
    17int count;
    18double avgAge;  // avg is a a good abbreviation for average
    19double gpa;  // good abbreviation
    20
    21// ---- Poor ----
    22int PtAc;  // unknown abbreviation
    23int v;  // not informative
    24double count = 1.5;  // name not matches the purpose
    25int NUMBER;  // not following naming convention
    
  • variable declaration - must be declared before being referred

  • initialization

    • assignment during declaration

    • not assignment! have different syntax!

     1// ==== declarations, initialization ====
     2
     3// ---- correct ----
     4int a;
     5int a = 10;
     6int a, b, c;
     7int a, b = 5, c = 10;
     8
     9// ---- wrong ----
    10int a
    11int a b c;
    12
    13// use before declare
    14a = 10;
    15int a;
    
    • constant variable

      • must be initialized!

      • can never be changed later!

      • all uppercase with under score

      • const keyword can be before or after the type

       1// ---- correct ----
       2const int CONSTANT1 = 100;
       3int const CONSTANT2 = 200;
       4
       5// --- Wrong ----
       6const int CONSTANT3;  // no initialization
       7CONSTANT1 = 200;  // modification not allowed
       8cin >> CONSTANT2;  // modification not allowed
       9
      10// ---- bad ----
      

Literal

How values are represented in the source code.

  • int 1, 100

  • double 3.0, 3e2, 3.0e-1

  • char 'a'

  • string "abc"

    • escape sequence \n, \t, \", \', \\ etc. in char or string literal

  • long 1000l

  • float 1.0f

  • unsigned int 100u

Assignment

  • = operator

  • assignment operation requires an lvalue on the left and an rvalue on the right

  • lvalue

    • something that binds to a defined memory address

    • variables

    • references

  • rvalue

    • anything that does or does not bind to a defined memory address

    • temporary and short-lived

    • literals

    • compound expressions e.g. x + y

    • temporary object e.g. string(argv[0])

  • short-handed assignment operators

    • +=

    • -=

    • *=

    • /=

    • %=

 1// ==== Assignment ====
 2
 3// ---- correct ----
 4int a = 10;
 5int b = a;
 6b = a;
 7a += b;
 8
 9double c = a;
10b = a * c;
11
12// ---- wrong ----
13a + b = 20;  // non-lvalue on the left
14a == 10;  // wrong operator
15
16// use without initial value
17int a;
18a = a + 1;
19a += 1;

Conversion and Type casting

  • Type conversion (implicit)

    1. assignment forces any type casting

    2. implicit conversion happens in operations between mixed types (the value of the type with smaller range will be converted to the type with lager range, a.k.a. widened)

  • Type casting (explicit)

    • explicit type casting static_cast<NewType>(variable)

    • Avoid C style type conversion like (int) doubleValue

 1// ==== conversion, type casting ====
 2
 3// ---- correct ----
 4int a = 10;
 5double b;
 6char c = 'L';
 7
 8b = a; // a converted to double
 9a = b; // b converted to int
10
11// c converted to int and added to a;
12// the resulting int converted to double when assigned to b
13b = a + c;
14
15// average without losing precision
16int total = 7;
17int count = 3;
18double average = static_cast<double>(total) / count;
19
20// convert to 3.210000
21double val = 3.213;
22double result = static_cast<int>(val * 100) / 100.0;
23
24// ---- wrong ----
25int total = 7;
26int count = 3;
27double average = total / count;  // lose precision, get 2.0, expect 2.3333...
28double average = static_cast<double>(total / count); // cast too late
29
30// ---- bad ----
31cout << ((int) 3.5) << endl;  // C-style type casting

Expressions

  • operators

    • arithmetic + - * / %

    • increase, decrease: ++, --

      • requires an lvalue

      • similar to += 1 or -= 1

      • prefix vs suffix

      • prefer prefix if possible (run faster, save memory)

    • relational == != < > <= >=

    • logic && || !

      • short circuit evaluation

        In the evaluation of logical expression with binary logical operators (&& and ||), the operands are evaluated from left to right. If the value of the right operand does not affect the result, it will be skipped in the evaluation.

    • bit-wise & | !

    • assignment =

    • other operator: ::, <<, >>, &, *, ., ->

  • Precedence rule (order of evaluation, arithmetic, relational, and logic only)

    1. ()

    2. ! logical negation

    3. - arithmetic negation

    4. *, /, % arithmetic multiplication, division, and modulo

    5. +, - arithmetic addition, subtraction

    6. >, <, >=, <= relational

    7. ==, != relational

    8. && logical and

    9. || logical or

  • Pitfalls

    • = vs ==

    • relational && || vs bit-wise & |

    • % on non-int

    • lose precision in integer division

    • chained range check 1 < a < 10

    • bool vs int, asymmetric interconversion

      • true -> 1, false -> 0

      • non-zero -> true, 0 -> false

     1// ==== operators ====
     2
     3// ---- correct ----
     4if (age > 1 && age < 10)
     5  cout << "Young child\n";
     6
     7// ---- wrong ----
     8double a = 10;
     9int b = a % 3;
    10
    11if (grade = 100)
    12  cout << "perfect!";
    13
    14if (age < 10 & age > 1)   // this actually works well but is a wrong syntax
    15  cout << "Young child\n";
    16
    17if (1 < age < 10)  // will compile but wrong!
    18  cout << "Young child\n";
    
  • Step-wise evaluation, in every step consider:

    • conversion and type casting

    • precedence rule

     1// ==== Expression ====
     2
     3// ---- step-wise evaluation ----
     4// given: x = 2
     5  (x + 5) / 4
     6= (2 + 5) / 4
     7= 7 / 4
     8= 1
     9
    10  static_cast<int>(19.5 / 3) + 5.0
    11= static_cast<int>(6.5) + 5.0
    12= 6 + 5.0
    13= 11.0
    14
    15  ((17 / 2 + 19 % 3 - 3 * 2 + 4 * 3) >= (5 + 2 * 4)) && !((((4 * 5) + 1) /2) == (7 / 3 + 2 * 5 - 2) || !(4 >= 3))
    16= ((8 + 1 - 6 + 12) >= (5 + 8)) && !(((20 + 1) / 2) == (2 + 10 - 2) || !(true))
    17= (15 >= 13) && !((21 / 2) == 10 || false)
    18= true && !(true || false)
    19= true && !true
    20= true && false
    21= false
    
  • evaluation tree

    Visual aid when evaluating complex expressions

    e.g. 3.0 / a + 5 < 8 && c > 'b' || d % 2 == 1

    graph eval_tree{
  "||" -- { "&&", "=="};
  "&&" -- {"<", ">"};
  "==" -- {"\%", "1"};
  "<" -- {"+", "8"};
  "+" -- {"/", "5"};
  "/" -- {"3.0", "a"};
  ">" -- {"c", "\'b\'"};
  "\%" -- {"d", "2"};
}

Core Concepts

Identifier

User defined names

Reserved word (keyword)

Names used by the language

Variable

A named container to store a value

Type

Storage format supported by the language

Variable initialization

Providing initial value to a variable when it is declared

Literal

Textual representation of fixed-values used in source code

Lvalue

An expression that binds to a defined memory address

Rvalue

An expression that does not bind to any defined memory address

Expression

Text representations in source code of something that evaluates to a value

Precedence rule

The order of evaluation of operators in an expression