C++. The concept of expression. Assignment operation. Converting and casting of types




The concept of expression. Assignment operation. Converting and casting of types. Initialization. Unified initialization


Contents


Search other websites:

1. What is called an expression in programming languages?

An expression is a union of statements, literals, and variables. Expressions are used to perform calculations, some actions, etc. Expressions can use the function names.

Examples of expressions.

a*8+5
Math::Sqrt(x)+Math::Sin(x+2)
sigma + gamma/20.0

 

2. What is the general form of the assignment operation? Examples

An assignment operation is used to specify a value for a variable. The value that is assigned can be the result of some expression.

In C/C++, the assignment operation is indicated by the symbol = (equal).

General view of the assignment operation:

variable = expression;

where

  • variable – the name of the variable to which the value of the expression is assigned;
  • expression – some expression that can be used according to the C/C ++ syntax.

Examples of the assignment operation.

a = 8;
b = a + Math::Sqrt(x)+Math::Sin(x+2);
sigma = (double) (2.0 / 8);

 

3. How is the assignment operation used when initializing variables?

General view of the assignment operation when initializing variables:

type variable_name = expression_or_value;

where

  • type – the type of the variable that is initialized;
  • expression_or_value – value of expression or constant value. If the value of the expression is used, then the variables included in this expression must already be declared at the moment (see example).

Examples of initializing variables.

...

// Initialization of variables
int a = 8, b = 25;
double c = 3.550093;
bool f = false;
char sym = 'A';

// Initialization of variables with expression
float x = 3.5;
float y = x + 2.8;
float z = x*x + y*y*y;
float zz = Math::Sqrt(z+5.0);

...

 






4. The concept of type conversion. Type conversion classifications

Variables of various types often appear in expressions. In such cases, the compiler performs the so-called cast or conversion of one type to another. In C++, the following classifications of type conversions exist:

  • classification by range of values;
  • classification by conversion method.

 

5. Classification by the range of the values when type conversion

When classifying a range of values, they distinguish:

  • narrowing type conversion. In this case, the larger data type narrows to the smaller one (the range of values narrows). Data loss may occur here;
  • extensible type conversions. With this conversion, the smaller data type expands to the larger data type (the range of values expands).

The following examples demonstrate these two kinds of transformations.

Example 1. Narrowing type conversion is demonstrated.

// 1. Narrowing data conversion resulting in data loss
// When initializing a variable
int d = 5.85; // double type is narrowed to int type, d = 5
cout << "d = " << d << endl; // d = 5 - data loss occurs

// When assigned in an expression
int k;
k = 2.3 + 0.5 + 0.1; // double type is narrowed to int type
cout << "k = " << k << endl; // k = 2 - data loss occurs

// 2. Narrowing conversion without data loss
short f = 2000; // int type is narrowed to short type
cout << "f = " << f << endl; // f = 2000

As you can see from the example, with narrowing type conversion data loss is possible.

Example 2. Extensive type conversion is demonstrated.

// Extensive type conversion
unsigned int t = 4000000000; // int expands to unsigned int without errors
cout << "t = " << t << endl;

In the example, the value 4000000000 is of type int. This value is correctly expanded to unsigned int type.

If the type of the variable t is specified as int

int t = 4000000000; // the number 4000000000 does not fit into the int type, t = -294967296 - data loss

then the value of t will be -294967296. This means that the number 4,000,000,000 will not fit in the int type.

 

6. Classification by conversion method. Implicit and explicit type conversion

Depending on the direction of the conversion, this conversion can be implemented in one of two ways:

  • implicit conversion. This conversion is called automatic. The compiler performs implicit conversion on its own without the intervention of a programmer;
  • explicit conversion or cast types. In this case, the type of conversion is entered in brackets.

 Example.

// 1. Implicit type conversion
int a = 25;
double x;
x = a; // implicit conversion int => double

float y = 78.3; // implicit conversion double => float

// 2. Explicit type conversion
int b;
b = (int)8.6; // b = 8, explicit conversion double => int

float z = (float)12.55; // explicit conversion double => float

 

7. Type conversion rules in expressions

If two operands of different types are found in the expression, then the following rules apply:

  • all operands are converted to the type of the largest operand. The process of this transformation is called integral promotion;
  • all types char and short int are converted to int type. The process of such a transformation is called an integer promotion;
  • if one of the operands is of type double, then any other operand is reduced to the type double. Even, in the case of type ‘char’, there is a cast to the type double;
  • after the conversion, both operands have the same type, which is the type of the result of the operation.

The following are examples of automatic type conversion.

Conversion between char and int types:

char c;
int d;

c = 'A';
d = c; // d = 65

d = 67;
c = d; // c = 'C'

Conversion between int and float types:

int d = 28;
float x;

x = d; // x = 28.0 - the 'float' type
d = 5.0 + 5; // d = 10 - the 'int' type

Conversion between float and double types:

float f;
double d;
int size;

f = 2.54f;
d = f; // d = 2.54 - 'double' type
d = 2.0f + 8.5; // the result of 'double' type

 

8. How are the conversions that are associated with the bool type?

If the expression contains an integer type, then the values of type bool are automatically converted to integers 0 and 1. The value 0 corresponds to the value false. The value 1 or non-zero value corresponds to true.

Example. A code snippet that demonstrates the conversion for the bool type

bool b;
int a;

a = 0;
b = a; // b = False

a = 1;
b = a; // b = True

a = 50;
b = a; // b = True

 

9. What is the general form of type cast operation?

The general form of the type cast operation is:

(type) expression

where

type – the type that you want to cast the result of evaluating an expression.

Examples of using a type cast operation.

int a;
float x;

a = 5;
x = a/2; // x = 2.0
x = (float)(a/2); // x = 2.0
x = (float)a/2; // x = 2.5 - 'float' type
x = a/2.0; // x = 2.5 - 'float' type

x = (int) (8/3.0);   // x = 2
x = (float) (8/3.0); // x = 2.666667

Recommendation. In order to obtain the necessary accuracy when evaluating expressions containing integer and real values, it is always desirable to do an operation of casting the type to the type of the variable to which the value is assigned.

 

10. What is unified (list) initialization? Example

Unified initialization is also called list initialization. This type of variable initialization has been added since C++ 11. Using unified initialization, you can set values for variables, arrays, and objects in a uniform way.

Syntactically unified initialization can be implemented in one of two ways:

1. Using the assignment operator (=). In this case, the initialization has the form:

type varName = { value };

2. Without using an assignment operator. The general view of such initialization is as follows:

type varName { value };

In the above forms:

  • type – data type, which can be the basic type (int, double, …), class, structure, enumeration, etc.;
  • varName – name of the variable to be initialized;
  • value – the value assigned to the varName variable.

An example of unified initialization of variables of different types.

#include <iostream>
using namespace std;

// Structure Point
struct Point
{
  int x;
  int y;
};

// Class Book
class Book
{
public:
  string title;
  float price;
};

void main()
{
  // Unified (list) initialization
  // 1. For a single variable of different types
  int i = { 25 };
  double x { 7.88 };
  float f = { -13.23 };
  char c { '+' };
  string s { "Hello world" };
  bool b = { true };

  // 2. For array
  int A[5] { 33 }; // A = { 33, 0, 0, 0, 0 }

  // 3. For structure Point
  Point pt{ 2, -3 }; // pt.x = 2; pt.y = -3

  // 4. Для объекта класса Book
  Book B{ "The title of book", 99.99f };

 

11. How does unified (list) initialization work in the case of conversion of a wider type to a less wide one? What is unified initialization for?

Unified initialization is useful when you need to implement verification of the correct type conversion during initialization. Unified initialization detects errors at the compilation stage in case data loss occurs. Data loss may occurs in the event of an implicit narrowing type conversion.

With unified initialization, the compiler generates an error:

  • when the trimming of the value assigned to the initialized variable occurs;
  • when the assigned value is outside the range of acceptable values of the type of the initialized variable. This situation is characteristic of integer and character variables.

During normal initialization (not unified), the compiler allows data loss and does not generate an error.

The following examples demonstrate the purpose of unified initialization.

Example 1. Let a variable of type int be set, which should be initialized in the usual way of initialization

int d = 7.88; // d = 7
cout << "d = " << d << endl; // d = 7

In this case, an implicit narrowing conversion will occur, since a variable of type int is assigned a value of type double. As a result, the value of d will be 7.

If you initialize the variable d in a unified way to initialize

int d = { 7.88 }; // compilation error!!!

then an error will occur at the compilation stage with the message

conversion from double to int requires a narrowing conversion

Example 2. This example shows that unified initialization can detect data loss errors for compatible types. Given a variable of type short, which is initialized with a value of type int that is outside the valid range of type short

// Normal initialization
short t = 200000000; // overflow, no compilation error, t = -15872

Here, the compiler does not generate errors, a normal overflow occurs and the value 200000000 is truncated to type short.

If you initialize the variable t in a unified way

// Unified initialization
short t{ 200000000 }; // overflow, compilation error

then the compiler will give an error message

conversion from int to short requires a narrowing conversion

 

12. What are the features of the use of parentheses and “space” characters in expressions?

To improve readability, the programs use:

  • characters “space”;
  • tabs (Tab keys);
  • round brackets ( ). Round brackets also allow you to increase the priority of the operations that are placed in them. The number of round brackets does not affect the speed of evaluating the expression.

 


Related topics