In the text on any natural language Four main elements can be distinguished: symbols, words, phrases and sentences. An algorithmic language also contains such elements, only words are called lexemes (elementary constructions), phrases are called expressions, and sentences are called operators. Tokens are formed from symbols, expressions from tokens and symbols, operators from symbols of expressions and tokens (Fig. 1.1)

Rice. 1.1. Compound algorithmic language

Thus, the elements of the algorithmic language are:

1) Alphabet of the SI++ language, which includes

- uppercase and lowercase Latin letters and underscore;

— Arabic numbers from 0 to 9;

— special characters “(),| ()+-/%*.\’:;&?<>=!#^

— whitespace characters (space, tab, newline characters).

2) Language lexemes are formed from symbols:

Identifiers– names of SI program objects. The identifier can use Latin letters, numbers and underscores. Uppercase and lowercase letters are different, for example PROG1, prog1 and Prog1 are three different identifiers. The first character must be a letter or underscore (not a number). Spaces in identifiers are not allowed.

Key(reserved) words are words that have a special meaning to the compiler. They cannot be used as identifiers.

— Operation signs are one or more symbols that define an action on the operands. Operations are divided into unary, binary and ternary according to the number of operands involved in this operation.

Constants– these are immutable quantities. There are integer, real, character and string constants. The compiler identifies a constant as a lexeme (an elementary construct) and assigns it to one of the types based on its appearance.

Separators– brackets, period, comma, space characters.

Constants in C++

Constant is a token that represents an image of a fixed numeric, string, or character value.

Constants are divided into 5 groups:

— real (floating point);

- enumerable;

- symbolic;

- string.

The compiler selects a lexeme and assigns it to one or another group, and then within the group to a certain type based on its form in the program text and its numerical value.

Integer constants can be decimal, octal, or hexadecimal. A decimal constant is defined as a sequence of decimal digits starting with something other than 0 unless that number is 0 (examples: 8, 0, 192345). An octal constant is a constant that always starts with 0. The 0 is followed by octal digits (examples: 016 - decimal value 14, 01). Hexadecimal constants are a sequence of hexadecimal digits preceded by the characters 0x or 0X (examples: 0xA, 0X00F).

Depending on the value of an integer constant, the compiler will represent it differently in computer memory (that is, the compiler will assign the corresponding data type to the constant).

Real constants have a different form of internal representation in computer memory. The compiler recognizes such constants by their type. Real constants can have two forms of representation: fixed-point and floating-point. Fixed-point constant type: [digits].[digits] (examples: 5.7, .0001, 41.). Floating-point constant type: [digits][.][digits]E|e[+|-][digits ] (examples: 0.5e5, .11e-5, 5E3). In writing real constants, either the integer or fractional parts, or the decimal point, or the exponent sign with an exponent can be omitted.

Enumerated constants are entered using keyword enum. These are ordinary integer constants that are assigned unique and easy-to-use notations. Examples: enum ( one=1, two=2, three=3, four=4);

enum (zero,one,two,three) – if you omit = signs and numeric values ​​in the definition of enumerated constants, then the values ​​will be assigned by default. In this case, the leftmost identifier will receive the value 0, and each subsequent one will increase by 1.

enum ( ten=10, three=3, four, five, six);

enum (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) ;

Character constants are one or two characters enclosed in apostrophes. Character constants consisting of one character are of type char and occupy one byte in memory, character constants consisting of two characters are of type int and occupy two bytes. Sequences starting with \ are called control sequences and are used:

— To represent symbols that do not have graphical display, for example:

\a – sound signal,

\b – return one step,

\n – line feed,

\t – horizontal tab.

— To represent characters: \ , ’ , ? , ”(\\, \’ ,\? ,\”).

- To represent characters using hexadecimal or octal codes (\073, \0xF5).

A string constant is a sequence of characters enclosed in quotation marks. Control characters can also be used within strings. For example: “\nNew line”,

“\n\”Algorithmic programming languages high level \”” .

Data types in C++

The data displays the surrounding world in the program. The purpose of the program is to process data. Data various types stored and processed differently. The data type defines:

1) internal representation of data in computer memory;

2) a set of values ​​that quantities of this type can take;

3) operations and functions that can be applied to data of this type.

Depending on the requirements of the task, the programmer selects a type for program objects. C++ types can be divided into simple and compound. Simple types include types that are characterized by a single value. C++ defines 6 simple types data:

There are 4 type specifiers that specify the internal representation and range of standard types

short

long

signed

unsigned

Typeint

Values ​​of this type are integers.

The size of the int type is not defined by the standard, but depends on the computer and the compiler. For a 16-bit processor, 2 bytes are allocated for it, for a 32-bit processor - 4 bytes.

If int is preceded by a short specifier, then 2 bytes are allocated for the number, and if the specifier is long, then 4 bytes are allocated. The amount of memory allocated for an object determines the set of valid values ​​that an object can take:

short int - takes 2 bytes, therefore, has a range of –32768 ..+32767;

long int – occupies 4 bytes, therefore has a range of –2,147,483,648..+2,147,483,647

The int type is the same as the short int type on 16-bit PCs and the long int type on 32-bit PCs.

The signed and unsigned modifiers also affect the set of valid values ​​that an object can take:

unsigned short int - takes 2 bytes, therefore, has a range of 0 ..65536;

unsigned long int – occupies 4 bytes, therefore, has a range of 0..+4 294 967 295.

Typechar

The values ​​of this type are the elements of a finite ordered set of characters. Each character is assigned a number, which is called the character code. 1 byte is allocated for a character type value. The char type can be used with the signed and unsigned specifiers. Signed char data can store values ​​in the range from –128 to 127. When using unsigned char data, values ​​can range from 0 to 255. The encoding is ASCII (American Standard Code foe International Interchange). Characters with codes from 0 to 31 are service characters and have independent meaning only in I/O statements.

Values ​​of type char are also used to store numbers from specified ranges.

Typewchar_t

Designed to work with a set of characters for which 1 byte is not enough to encode, for example Unicode. The size of this type generally corresponds to the short type. String constants of this type are written with the L prefix: L“String #1”.

Typebool

The type bool is called boolean. Its values ​​can take the values ​​true and false. The internal form of false is 0, any other value is interpreted as true.

Floating point types.

Internal representation real number consists of 2 parts: mantissa and order. On IBM-compatible PCs, float values ​​occupy 4 bytes, of which one bit is allocated for the mantissa, 8 bits for the exponent and 24 for the mantissa.

Double values ​​occupy 8 bytes, 11 and 52 bits are allocated for the exponent and mantissa, respectively. The length of the mantissa determines the precision of the number, and the length of the order of its range.

If a long specifier precedes a double type name, bytes are allocated for the value.

Typevoid

The main types also include the void type. The set of values ​​of this type is empty.

Variables

A variable in SI++ is a named area of ​​memory that stores data of a specific type. A variable has a name and a value. The name is used to refer to the memory area in which the value is stored. Before use, any variable must be declared. Examples:

General view of the description operator:

[memory class]type name [initializer];

The memory class can take the following values: auto, extern, static, register. The memory class determines the lifetime and scope of a variable. If the memory class is not specified explicitly, the compiler determines it based on the declaration context. The lifetime can be permanent - during the execution of the program or temporary - during the block. Scope is a part of the program text from which normal access to a variable is allowed. Typically the scope is the same as the scope. Except for the case when there is a variable with the same name in the inner block.

Const – indicates that this variable cannot be changed (named constant).

When describing, you can assign an initial value to a variable (initialization).

Memory classes:

auto – automatic local variable. The auto specifier can only be specified when defining block objects, for example, in the body of a function. These variables are allocated memory when entering a block and freed when exiting it. Outside the block, such variables do not exist.

extern is a global variable, it is located in another place in the program (in another file or further down the text). Used to create variables that are available in all program files.

static is a static variable; it exists only within the file where the variable is defined.

register - similar to auto, but memory for them is allocated in processor registers. If this is not possible, then the variables are processed as auto.

Int a; //global variable void main())( int b;//local variable extern int x;//variable x is defined elsewhere static int c;//local static variable a=1;//assignment to global variable int a;/ /local variable a a=2;//assignment to a local variable::a=3;//assignment to a global variable ) int x=4;//definition and initialization of x

In the example, the variable a is defined outside of all blocks. The scope of the variable a is the entire program, except for those lines where the local variable a is used. Variables b and c are local, their scope is block. The lifetime is different: memory for b is allocated when entering the block (since the default memory class is auto), and is freed when exiting it. A variable with (static) exists while the program runs.

If the initial value of the variables is not explicitly set during definition, the compiler resets global and static variables to zero. Automatic variables are not initialized.

The variable name must be unique within its scope.

A variable declaration can be done either as a declaration or a definition. The declaration contains information about the memory class and the type of the variable; the definition, along with this information, instructs the memory to be allocated. In the example extern int x; - declaration, and the rest - definitions.

Operation signs in C++

Operation signs provide the formation of expressions. Expressions consist of operands, operator symbols, and parentheses. Each operand is, in turn, an expression or a special case of an expression - a constant or a variable.

Unary operations

& getting operand address
* Referring to an address (dereferencing)
unary minus, changes the sign of the arithmetic operand
~ bitwise inversion of the internal binary code of an integer operand (bitwise negation)
! logical negation (NOT). 0 is false and non-0 is true, the negation of 0 is 1, the negation of any non-zero number is 0.
++ Increase by one:

prefix operation - increments the operand before it is used,

The postfix operator increments the operand after it has been used.

int a=(m++)+n; // a=4,m=2,n=2

int b=m+(++n);//a=3,m=1,n=3

— — decrease by one:

prefix operation - reduces the operand before it is used,

The postfix operator decrements an operand after it has been used.

sizeof calculating the size (in bytes) of an object of the type that has the operand

has two forms

sizeof expression

sizeof(float)//4

sizeof(1.0)//8, since real constants are of double type by default

Binary operations.

Additive:

Multiplicative:

Shift operations (defined for integer operands only).

Expression format with shift operation:

left operand shift operation right operand

Bitwise operations:

Comparison operations: the result is true(not 0) or false(0)

Logical binary operations:

Assignment Operators

Etc.

Simple assignment format:

operand1=operand2

A left-valid value (L-value) is an expression that addresses a certain area of ​​memory, i.e., a value can be stored in it. This name comes from the assignment operation, since it is the left side of the assignment operation that determines in which memory area the result of the operation will be stored. Variable is special case left-admissible expression.

Conditional operation.

Unlike unary and binary operations, it uses three operands.

Expression1 ? Expression2: Expression3;

The value of expression1 is calculated first. If it is true, then the value of expression2 is evaluated and becomes the result. If, when evaluating expression1, 0 is obtained, then the value of expression3 is taken as the result.

For example:

x<0 ? -x: x ; //вычисляется абсолютное значение x.

Explicit (conversion) type casting operation.

There are two forms: canonical and functional:

1) (type_name) operand

2) type_name (operand)

(int)a //canonical form

int(a) //functional form

Expressions

You can construct expressions from constants, variables, delimiters, and operator symbols. Each expression represents a rule for calculating a new value. If the expression forms an integer or real number, then it is called arithmetic. A pair of arithmetic expressions joined by a comparison operation is called a relation. If the relation has a non-zero value, then it is true, otherwise it is false.

Operator precedence in expressions

Rank Operations
1 () -> .
2 ! ~ - ++ - & * (type) sizeof type()
3 */% (multiplicative binary)
+ — (additive binary)
5 << >> (bit shift)
6 < > <= >= (relationship)
7 == != (relations)
8 & (bitwise conjunction “AND”)
9 ^ (bitwise exclusive "OR")
10 | (bitwise disjunction “OR”)
11 && (conjunction “AND”)
12 || (disjunction “OR”)
13 ?: (conditional operation)
14 = *= /= %= -= &= ^= |= <<= >>= (assignment operator)
15 , (comma operation)

Last update: 06/19/2017

A separate set of operations represents conditional expressions. Such operations return boolean value, that is, a bool value: true if the expression is true, and false if the expression is false. Such operations include comparison operations and logical operations.

Comparison Operations

Comparison operations compare two operands and return a bool value - true if the expression is true and false if the expression is false.

    Compares two operands for equality. If they are equal, then the operation returns true; if they are not equal, then false is returned:

    B; // false

    Compares two operands and returns true if the operands are not equal and false if they are equal.

    Int a = 10; int b = 4; bool c = a != b; // true bool d = a!=10; // false

    Operation "less than". Returns true if the first operand is less than the second, and false if the first operand is greater than the second:

    Int a = 10; int b = 4; bool c = a< b; // false

    Operation "more than" Compares two operands and returns true if the first operand is greater than the second, otherwise returns false:

    Int a = 10; int b = 4; bool c = a > b; // true bool d = a > 25; // false

    Less than or equal to operation. Compares two operands and returns true if the first operand is less than or equal to the second. Otherwise it returns false.

    Int a = 10; int b = 4; bool c = a<= b; // false bool d = a <= 25; // true

    Greater than or equal to operation. Compares two operands and returns true if the first operand is greater than or equal to the second, otherwise returns false:

    Int a = 10; int b = 4; bool c = a >= b; // true bool d = a >= 25; // false

Operations<, > <=, >= have higher priority than == and !=.

Logical operations

Also defined in C# logical operators, which also return a value of type bool . They take bool values ​​as operands. Typically applied to relationships and combining multiple comparison operations.

    Logical addition operation or logical OR. Returns true if at least one of the operands returns true.

    Bool x1 = (5 > 6) | (4< 6); // 5 >6 - false, 4< 6 - true, поэтому возвращается true bool x2 = (5 >6) | (4 > 6); // 5 > 6 - false, 4 >

    Logical multiplication or logical AND operation. Returns true if both operands are true at the same time.

    Bool x1 = (5 > 6) & (4< 6); // 5 >6 - false, 4< 6 - true, поэтому возвращается false bool x2 = (5 < 6) & (4 < 6); // 5 < 6 - true, 4 < 6 - true, поэтому возвращается true

    Logical addition operation. Returns true if at least one of the operands returns true.

    Bool x1 = (5 > 6) || (4< 6); // 5 >6 - false, 4< 6 - true, поэтому возвращается true bool x2 = (5 >6) || (4 > 6); // 5 > 6 is false, 4 > 6 is false, so false is returned

    Logical multiplication operation. Returns true if both operands are true at the same time.

    Bool x1 = (5 > 6) && (4< 6); // 5 >6 - false, 4< 6 - true, поэтому возвращается false bool x2 = (5 < 6) && (4 < 6); // 5 < 6 - true, 4 < 6 - true, поэтому возвращается true

    Logical negation operation. Performed on one operand and returns true if the operand is false. If the operand is true, then the operation returns false:

    Bool a = true; bool b = !a; // false

    Exclusive OR operation. Returns true if either the first or second operand (but not both) is true, otherwise returns false

    Bool x5 = (5 > 6) ^ (4< 6); // 5 >6 - false, 4< 6 - true, поэтому возвращается true bool x6 = (50 > 6) ^ (4 / 2 < 3); // 50 >6 - true, 4/2< 3 - true, поэтому возвращается false

Here we have two pairs of operations | and || (as well as & and &&) perform similar actions, but they are not equivalent.

In the expression z=x|y; Both x and y values ​​will be calculated.

In the expression z=x||y; first, the x value will be calculated, and if it is true, then calculating the y value no longer makes sense, since in any case, z will already be true. The value of y will only be calculated if x is false

The same goes for the &/&& operator pair. The expression z=x will evaluate both x and y.

In the expression z=x&, the value x will first be calculated, and if it is equal to false, then calculating the value of y no longer makes sense, since in our case z will already be equal to false in any case. The value of y will only be calculated if x is true

Therefore the operations || and && are more convenient in calculations, as they reduce the time it takes to calculate the value of an expression, and thereby improve performance. And operations | and & are more suitable for performing bitwise operations on numbers.

Various operations can be performed on objects in the C language:

  • assignment operations;
  • relational operations;
  • arithmetic;
  • brain teaser;
  • shear operations.

The result of the operation is a number.

Operations can be binary or unary.
Binary operations are performed on two objects, unary operations on one.

Assignment operator

The assignment operation is denoted by the = symbol and is performed in 2 steps:

  • the expression on the right side is calculated;
  • the result is assigned to the operand on the left side:

object = expression;

Example:

int a = 4; // variable a is assigned the value 4
int b;
b = a + 2; // variable b is assigned the value 6 calculated on the right side

If the objects on the left and right sides of the assignment operation have different types An explicit type cast operation is used.
object = (type)expression;

Example:

float a = 241.5;
// Before calculating the remainder of the division, a is cast to an integer type
int b = (int )a % 2; // b = 1

Relation operations

Basic relation operations:

  • == equivalent - equality test;
  • != not equal - check for inequality;
  • < less;
  • > more;
  • <= less or equal;
  • >= more or equal.

Relational operations are used to organize conditions and branches. The result of these operations is 1 bit, the value of which is 1 if the result of the operation is true, and equal to 0 if the result of the operation is false.

Arithmetic operations

Basic binary operations, in decreasing order of priority:

  • * - multiplication;
  • / - division;
  • + - addition;
  • - subtraction;
  • % is the remainder of an integer division.

Basic unary operations:

  • ++ — incrementing (increase by 1);
  • -- — decrementation (decrease by 1);
  • — sign change.

The result of evaluating an expression containing incrementing or decrementing operations depends on where the operation sign is located (before or after the object). If the operation is located before the object, then the value of the variable is first changed to 1, and then this value is used to perform the following operations. If the operation ++ or located after the variable, the operation is performed first, and then the value of the variable is changed to 1.

Example:

Binary arithmetic operations can be combined with the assignment operator:

  • object *= expression; // object = object * expression
  • object /= expression; // object = object / expression
  • object += expression; // object = object + expression
  • object -= expression; // object = object - expression
  • object %= expression; // object = object % expression

Logical operations

Logical operations are divided into two groups:

  • conditional;
  • bitwise.

Conditional logical operations are most often used in if condition testing operations and can be performed on any objects. Result of conditional logical operation:

  • 1 if the expression is true;
  • 0 if the expression is false.

In general, all values ​​other than zero are interpreted as true by conditional logical operators.

Basic conditional logical operations:

  • && — And (binary) - simultaneous execution of all operations of the relation is required;
  • || — OR (binary) - at least one relational operation is required;
  • ! - NOT (unary) - non-execution of the relational operation is required.

Bitwise logical operations operate on bits, each of which can take only two values: 0 or 1.

Basic bitwise logical operations in the C language:

  • & conjunction (logical AND) is a binary operation whose result is equal to 1 only when both operands are one (in the general case, when all operands are one);
  • | disjunction (logical OR) is a binary operation whose result is 1 when at least one of the operands is 1;
  • ~ inversion (logical NOT) is a unary operation, the result of which is 0 if the operand is one, and equal to 1 if the operand is zero;
  • ^ Exclusive OR is a binary operation whose result is 1 if only one of the two operands is 1 (in general, if there is an odd number of ones in the input set of operands).

For each bit, the result of the operation will be obtained in accordance with the table.

a b a&b a | b ~a a^b
0 0 0 0 1 0
0 1 0 1 1 1
1 0 0 1 0 1
1 1 1 1 0 0

Example:

1
2
3
4
5
6
7

unsigned char a = 14; // a = 0000 1110
unsigned char b = 9; // b = 0000 1001
unsigned char c, d, e, f;
c = a&b; // c = 8 = 0000 1000
d = a | b; // d = 15 = 0000 1111
e = ~a; // e = 241 = 1111 0001
f = a^b; // f = 7 = 0000 0111


Bitwise operations allow you to set and reset individual bits of a number. For this purpose it is used bit masking. Masks corresponding to the setting of each bit in a byte are presented in the table

Bit Mask
0 0x01
1 0x02
2 0x04
3 0x08
4 0x10
5 0x20
6 0x40
7 0x80

To set a specific bit, you need to set the corresponding bit of the mask to 1 and perform a bitwise logical OR operation with a constant that is a mask.

Since in the previous article I used a logical operation for the first time, I will tell you what they are, how many there are and how to use them.

There are three logical operations in C++:

  1. The logical operation AND && is already known to us;
  2. Logical OR operation || ;
  3. Logical operation NOT ! or logical negation.

Logical operations form a complex (composite) condition from several simple (two or more) conditions. These operations simplify the structure of the program code several times. Yes, you can do without them, but then the number of ifs increases several times, depending on the conditions. The following table briefly describes all logical operations in the C++ programming language for constructing logical conditions.

Now you should understand the difference between the logical AND operation and the logical OR operation so as not to be confused in the future. It's time to get acquainted with the data type bool–logical. This type data can take two values: true and false. The condition being tested in select statements has a bool data type. Let's consider the working principle of the following program, and everything will be clear with all these logical operations.

// or_and_not.cpp: Defines the entry point for the console application. #include "stdafx.h" #include using namespace std; int main(int argc, char* argv) ( bool a1 = true, a2 = false; // declaration of boolean variables bool a3 = true, a4 = false; cout<< "Tablica istinnosti log operacii &&" << endl; cout << "true && false: " << (a1 && a2) << endl // логическое И << "false && true: " << (a2 && a1) << endl << "true && true: " << (a1 && a3) << endl << "false && false: " << (a2 && a4) << endl; cout << "Tablica istinnosti log operacii ||" << endl; cout << "true || false: " << (a1 || a2) << endl // логическое ИЛИ << "false || true: " << (a2 || a1) << endl << "true || true: " << (a1 || a3) << endl << "false || false: " << (a2 || a4) << endl; cout << "Tablica istinnosti log operacii !" << endl; cout << "!true: " << (! a1) << endl // логическое НЕ << "!false: "<< (! a2) << endl; system("pause"); return 0; }

Lines 9 and 10should be clear to you, since variables of the type are initialized here bool . Moreover, each variable is assigned a value true or false . Beginning with 9th line and ending 20th, shows the use of logical operations. The result of the program (see Figure 1).

Tablica istinnosti log operacii && true && false: 0 false && true: 0 true && true: 1 false && false: 0 Tablica istinnosti log operacii || true || false: 1 false || true: 1 true || true: 1 false || false: 0 Tablica istinnosti log operacii ! !true: 0 !false: 1 To continue, press any key. . .

Figure 1 - C++ logical operations

You probably have a question, “What are these zeros and ones?” If there is a question, then it needs to be answered. I answer: “A zero is a representation of the logical value false, and ones are a logical value true.” Let me briefly explain some points. Composite condition using boolean AND is true only if both prime conditions are true. In all other cases, the compound condition is false. A compound condition using logical OR is false only if both simple conditions are false. In all other cases, the compound condition is true. Logical negation NOT is a unary operator, and it does not combine two conditions, unlike logical operators AND And OR, which are binary operations. Logical negation allows you to reverse the meaning of the condition, which in some cases is very convenient. A condition with logical negation is true if the same condition is false without negation, and vice versa.

Tags: C logical operators, logical negation, logical NOT, !, logical OR, logical addition, OR, logical multiplication, logical AND, AND, order of execution of logical operators

Logical operators

Boolean operators are operators that take Boolean values ​​(false or true) as arguments and return a Boolean value. Like ordinary operators, they can be unary (unary, that is, take one argument), double (binary, take two arguments), triple, etc.

A special feature of the C language is that it does not have a type that stores a Boolean value (false or true). In C, an integer 0 is considered a lie (logical zero), and any non-zero integer will be a logical truth. For example

#include #include void main() ( char boolValue = -71; if (boolValue) ( ​​printf("boolValue is true"); ) else ( printf("boolValue is false"); ) _getch(); )

Boolean values ​​are usually generated by comparison operators (==, !=, >,<, >=. <=).

There are three logical operators in the C language: AND, OR and NOT. Let's start with the simplest

Logical negation

The NOT operator is used to invert the value of an argument. That is, if it was passed truth, it will return false, if it received false as an argument, it will return truth.

Logical operator NOT
X NOT X
0 1
1 0

In C, negation is represented by the operator !. For example

#include #include void main() ( int i = 0; if (i) ( printf("i is true\n"); ) if (!i) ( printf("i is not true\n"); ) if (!! i) ( printf("i is not not true\n"); ) if (!!!i) ( printf("i is not not true\n"); ) _getch(); )

As in ordinary logic, the law of double negation applies here - the negation of the negation can be omitted.

Logical AND

The AND operator (AND, logical multiplication) returns true if and only if both arguments are true.


Logical operator AND
X Y X AND Y
0 0 0
0 1 0
1 0 0
1 1 1

In simple terms, logical multiplication is represented by the && operator. For example, the task is that only adult male citizens are allowed into the military spacemarines circle. That is, only one for whom two conditions are true at the same time can become a candidate

#include void main() ( char gender; unsigned int age; printf("Enter gender ("M" or "F")\n"); scanf("%c", &gender); printf("Enter age\n") ; scanf("%u", &age); if (gender == "M" && age > 17) ( printf("Wellcome"); ) else ( printf("Go away"); ) _getch(); )

The AND operator can be applied sequentially to multiple arguments. It is subject to associative and commutative laws. We will improve the program and also introduce growth:

#define _CRT_SECURE_NO_WARNINGS #include #include void main() ( char gender; unsigned int age; unsigned int height; printf("Enter gender ("M" or "F")\n"); scanf("%c", &gender); printf("Enter age \n"); scanf("%u", &age); printf("Enter height\n"); scanf("%u", &height); if (gender == "M" && age > 17 && height > = 180) ( printf("Wellcome"); ) else ( printf("Go away"); ) _getch(); )

The condition could also be written

(gender == "M" && age > 17) && height >= 180

Gender == "M" && (age > 17 && height >= 180)

(age > 17 && height >= 180) && gender == "M"

Logical OR

The logical OR operator (logical addition, OR) is true when at least one of its arguments is true.


Logical operator OR
X Y X OR Y
0 0 0
0 1 1
1 0 1
1 1 1

In C, OR is represented by the operator ||. For example, let's improve the program: now gender can be entered in both capital and small letters

#define _CRT_SECURE_NO_WARNINGS #include #include void main() ( char genderInput; char gender; unsigned int age; unsigned int height; printf("Enter gender ("M" or "F")\n"); scanf("%c", &genderInput); printf( "Enter age\n"); scanf("%u", &age); printf("Enter height\n"); scanf("%u", &height); if (genderInput == "M" || genderInput = = "m") ( gender = 1; ) else ( gender = 0; ) if ((age > 17 && height >= 180) && gender) ( printf("Wellcome"); ) else ( printf("Go away" ); ) _getch(); )

As with the AND operator, OR is commutative and associative.

Operators can be mixed together to create complex operators

#define _CRT_SECURE_NO_WARNINGS #include #include void main() ( char gender; unsigned int age; unsigned int height; printf("Enter gender ("M" or "F")\n"); scanf("%c", &gender); printf("Enter age \n"); scanf("%u", &age); printf("Enter height\n"); scanf("%u", &height); if ((age > 17 && height >= 180) && (gender == "M" || gender == "m")) ( printf("Wellcome"); ) else ( printf("Go away"); ) _getch(); )

You just have to remember that the negation operator has higher priority than AND or OR, so it will be executed first. If there may be a situation where the order of execution is not clear, define it using parentheses.

Example: De Morgan's law. To change AND to OR (or vice versa), you must invert the values ​​of all operands, replace AND with OR (or OR with AND), and invert the final result. In the case of our condition

(age > 17 && height >= 180) && (gender == "M" || gender == "m")

Let's first consider the piece

(age > 17 && height >= 180)

Reverse all values

(!(age > 17) && !(height >= 180))

replace the && operator with ||

(!(age > 17) || !(height >= 180))

and invert the answer

!(!(age > 17) || !(height >= 180))

As you can see, the result is the same. It's obvious that

!(age > 17)

equivalent

Age<= 17

Thus, let's change the condition

!(age<= 17 || height < 180)

Let's change the second bracket in the same way

(gender == "M" || gender == "m")

!(gender != "M" && gender != "m")

!(age<= 17 || height < 180) && !(gender != "M" && gender != "m")

Now you can apply the same rule for the entire expression

!((age<= 17 || height < 180) || (gender != "M" && gender != "m"))

Order of execution of logical operators

Let's consider the expression

A && b && c && d

where a, b, c, d are logical values. The entire expression is true if and only if all operands are true. If at least one of the operands is false, then the rest are no longer important. Therefore, to optimize performance, the calculation proceeds from left to right and stops as soon as the first operand is found to be zero.

In C, the assignment operator can return a value. Sometimes it is used directly in a condition:

#define _CRT_SECURE_NO_WARNINGS #include #include #include void main() ( int a = 0; int *p = if (a && (p = (int*) malloc(sizeof(int) * 2))) ( printf("memory was allocated"); ) free(p ); _getch(); )

In this case, the malloc operator will not be executed, since the first operand a is equal to 0 (accordingly, the entire expression is equal to zero). Thus, the free operator will try to clear memory that it cannot clear (since p will continue to refer to a). If we change a = 1, then everything will work without problems.

The same thing happens when executing ||. Expression

A || b || c || d

is executed from left to right until it encounters the first non-zero value. After this, execution stops because the entire expression is known to be true.