# Variables and Basic Types

C++ keywords & alternative operator names:

```
alignas alignof and and_eq asm 
auto bitand bitor bool break
case catch char char8_t char16_t
char32_t class compl concept const 
const_cast consteval constexpr constinit continue 
co_await co_return co_yield decltype default
delete do double dynamic_cast else 
enum explicit export extern false
float for friend goto if 
inline int long mutable namespace 
new noexcept not not_eq nullptr 
operator or or_eq private protected 
public register reinterpret_cast requires return 
short signed sizeof static static_assert
static_cast struct switch template this
thread_local throw true try typedef 
typeid typename union unsigned using 
declaration using directive virtual void 
volatile wchar_t while xor xor_eq
```

## Compound Type

A declaration is a **base type** followed by a list of **declarators**.

### References

When we define a reference, we **bind** the reference to its initializer. There is no way to rebind a reference to refer to a different object.

```c++
int i = 0;
int& r1 = i; // Legal but might be misleading.The declarator should be put with the variable name.
int &r2 = i; // Good.
```

Two exceptions to the rule that **the type of a reference** must match **the type of the object to which it refers**:

* We can initialize a reference to const from any expression that can be converted

### Pointers

**Null pointers**:

```c++
int *p1 = nullptr; // Equivalent to int *p1 = 0;
int *p2 = 0; // Directly initializes p2 from the literal constant 0.

int *p3 = NULL; // Equivalent to int *p3 = 0; Must #include <cstdlib>
```

A `void*` pointer holds an address, but the type of the object at that address is unknown.

### Discussion

```c++
// i is an int; p is a pointer to int; r is a reference to int 
int i = 1024, *p = &i, &r = i;
```

A reference is not an object such that we may not have a pointer to a reference.

A pointer is an object, we can define a reference to a pointer.

```c++
int *p; // p is a pointer to int
int *&r = p; // r is a reference to the pointer p
```

**Suggestion**: understand pointer or reference declarations by reading from right to left.

## `const` Qualifier

**Because we can’t change the value of a `const` object after we create it, it must be initialized.**

By default, `const` objects are local to a file.

To define a single instance of a **const variable** that can be shared acrossed files, we use the keyword `extern` on both its definition and declaration(s):

```c++
// In file_1.cc defines and initializes a const that is accessible to other files.
extern const int bufSize = fcn();
// In file_1.h
extern const int bufSize; // Same bufSize as defined in file_1.cc
```

### **References to** `const`

```c++
const int ci = 1024;
const int &r1 =  ci; // OK: both reference and underlying object are const
r1 = 42; // ERROR: r1 is a reference to const
int &r2 = ci; // ERROR: nonconst reference to a const object
```

Because we cannot assign directly to `ci`, we also should not be able to use a reference to change ci.

> reference to const == const reference

We can initialize a reference to const from any expression that can be converted

```c++
double dval = 3.14;
const int &ri = dval;
```

The code is transdformed by the compiler into:

```c
const int temp = dval;
const int &ri = temp;
```

A reference to const **restricts only what we can do** through that reference. Binding a reference to `const` to an object says nothing about whether the underlying object itself is `const`.

### **Pointers and** `const`

```c++
const double pi = 3.14; // pi is const; its value may not be changed 
double *ptr = &pi; // Error: ptr is a plain pointer
const double *cptr = &pi; // Ok:cptr may point to a double that is const
*cptr = 42; // Error: cannot assign to *cptr
```

**`const` Pointers**

> const pointer != pointer to const

Like any other const object, a **const** **pointer** must be initialized, and once initialized, its value (i.e., the address that it holds) may not be changed.

```c++
int errNumb = 0;
int *const curErr = &errNumb; // curErr will always point to errNumb 
const double pi = 3.14159;
const double *const pip = &pi; // pip is a const pointer to a const object
```

### Top-Level `const`

We use the term **top-level** **const** to indicate that the pointer itself is a const. When a pointer can point to a const object, we refer to that const as a **low-level** **const**.

```c++
const int *p1; // This is a fucking low-level const.
int const* p2; // This is a fucking top-level const.
int *const p2; // This is also a fucking top-level const.
```

### `constexpr` and Constant Expressions

A **constant expression** is an expression whose value cannot change and that can be evaluated at compile time.

```c++
const int max_files = 20; // max_files is a constant expression
const int limit = max_files + 1; // limit is a constant expression
int staff_size = 27; // staff_size is not a constant expression
const int sz = get_size(); // sz is not a constant expression
```

Under the new standard, we can ask the compiler to verify that a variable is a constant expression by declaring the variable in a **constexpr** declaration. Variables declared as `constexpr` are implicitly const and must be initialized by constant expressions.

```c++
constexpr int mf = 20; // 20 is a constant expression
constexpr int limit = mf + 1; // mf + 1 is a constant expression 
constexpr int sz = size(); // OK only if size is a constexpr function
```

The types we can use in a constexpr are known as “literal types” because they are simple enough to have literal values.

We can initialize a `constexpr` pointer from the `nullptr` literal or the literal (i.e., constant expression) `0`. We can also point to (or bind to) an object that remains at **a fixed address** (an object defined outside of any function).

```c++
constexpr int *np = nullptr; // np is a constant pointer to int that is null 
int j = 0;
constexpr int i = 42; // type of i is const int
// i and j must be defined outside any function
constexpr const int *p = &i; // p is a constant pointer to the const int i 
constexpr int *p1 = &j; // p1 is a constant pointer to the int j
```

***

It is important to understand that when we define a pointer in a `constexpr` declaration, the `constexpr` specifier applies to the pointer, not the type to which the pointer points:

```c++
const int *p = nullptr; // p is a pointer to a const int
constexpr int *q = nullptr; // q is a const pointer to int
```

## Dealing with Types

### Type Aliases

```c++
typedef double wages; // wages is a synonym for double
typedef wages base, *p; // base is a synonym for double, p for double*
```

The new standard introduced a second way to define a type alias, via an **alias declaration**:

```c++
using SI = Sales_item; // SI is a synonym for Sales_item
```

\*\*Do not intepreting a declaration that uses a type alias by conceptually replacing the alias with its corresponding type. \*\*

```c++
typedef char *pstring;
const pstring cstr = 0; // cstr is a constant pointer to char, char * is the base type
const char *cstr=0; // the base type is const char
```

### **The** **auto** Type Specifier

```c++
auto i = 0, *p = &i; // ok:i is int and p is a pointer toint
```

**Compound Types, `const` and `auto`**

```c++
int i = 0, &r = i;
auto a = r; // a is an int(r is an alias fori, which has type int)
```

`auto` ordinarily ignores top-level consts.

```c++
const int ci = i, &cr = ci;
auto b = ci; // b is an int (top-level const in ci is dropped)
auto c = cr; // c is an int (cr is an alias for ci whose const is top-level) 
auto d = &i; // d is an int*(& of an int object is int*)
auto e = &ci; // e is const int* (& of a const object is low-level const)
```

If we want the deduced type to have a top-level const, we must say so explicitly:

```c++
const auto f=ci; // deduced type of ci is int;f has type const int
```

We can also specify that we want a reference to the auto-deduced type. When we ask for a reference to an auto-deduced type, top-level consts in the initializer are not ignored.

```c++
auto &g = ci; // g is a const int& that is bound to ci 
auto &h = 42; // error: we can’t bind a plain reference to a literal 
const auto &j = 42; // ok: we can bind a const reference to a literal
```

### **The** `decltype` Type Specifier

```c++
decltype(f()) sum = x; // sum has whatever type f returns
```

Here, the compiler does not call f, but it uses the type that such a call would return as the type for sum.

When the expression to which we apply decltype is a variable, decltype returns the type of that variable, including top-level const and reference:

```c++
const int ci = 0, &cj = ci;
decltype(ci) x = 0; // x has type const int
decltype(cj) y = x; // y has type const int& and is bound to x
decltype(cj) z; // error: z is a reference and must be initialized
```

`decltype` **and References**

Generally speaking, `decltype` returns a reference type for **expressions** that yield **objects that can stand on the left-hand side of the assignment**.

***The above rule only apply to EXPRESSIONs. For example,****&#x20;****`i`****&#x20;****is an variable while****&#x20;****`i+0`****&#x20;****and****&#x20;****`(i)`\*\*\*\* \*\*\*\*are expressions.***

```c++
// decltype of an expression can be a reference type
int i = 42, *p = &i, &r = i;
decltype(r + 0) b; // ok: addition yields an int; b is an (uninitialized) int 
decltype(*p) c; // error: c is int& and must be initialized
```

The dereference operator is an example of an expression for which decltype returns a reference.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://osh.fducslg.com/notes/c++/c02-variables-and-basic-types.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
