93 lines
6.1 KiB
C
93 lines
6.1 KiB
C
|
|
int main(){
|
|||
|
|
// переменная типа int (integer) с именем a
|
|||
|
|
int a = 1;
|
|||
|
|
int b = 2;
|
|||
|
|
return a+b;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// напоминаю, `echo %ERRORLEVEL%` после запуска
|
|||
|
|
|
|||
|
|
// Базовые "элементарные" типы:
|
|||
|
|
int unused_code(){
|
|||
|
|
char symbol = 'a'; // ASCII символ. Практически, это все символы на клавиатуре кроме кириллицы
|
|||
|
|
float number = 2.3; // дробное число
|
|||
|
|
unsigned int notnull = 2; // целое беззнаковое число.
|
|||
|
|
|
|||
|
|
// Строка в C определяется как массив ASCII символов, который заканчивается символом конца строки '\0'.
|
|||
|
|
// Я не хочу сейчас говорить про массивы, т.к. они связаны с понятием указателя, поэтому отмечу только следующее:
|
|||
|
|
char string1[] = {'S', 't', 'r', 'i', 'n', 'g', '\0'}; // так выглядит создание массива с заранее заданными значениями
|
|||
|
|
char string2[] = "String"; // для строк есть более удобный синтаксис. строка 2 хранит то же самое, что и строка 1
|
|||
|
|
|
|||
|
|
// Что можно делать с переменными, кроме как создавать?
|
|||
|
|
|
|||
|
|
int c; // их можно задавать без указания значения. Тогда их байты могут быть
|
|||
|
|
// как случайными (заполнеными мусором), так и заполнеными нулями, но на это лучше не полагаться
|
|||
|
|
|
|||
|
|
c = notnull; // в данном примере проблемы нет, так как у notnull значение 2, но
|
|||
|
|
// если у переменных разный тип, то нет гарантии того, что присваивание значения
|
|||
|
|
// одной переменной другой будет выполнять то, что вы думаете
|
|||
|
|
c = number; // нам не нужно указывать, что у c тип int, т.к. это уже было сделано ранее.
|
|||
|
|
// Аналогично, т.к. int может хранить значение 2, то в данном контексте операция законна,
|
|||
|
|
// но не для любого float так можно делать.
|
|||
|
|
|
|||
|
|
// Т.к. компьютер воспринимает все примитивные типы как числа, то:
|
|||
|
|
// Можно применять побитовые логические операции (число считается за вектор битов):
|
|||
|
|
int a = 5, b = 3;
|
|||
|
|
// ЛОГИЧЕСКОЕ И: &, ЛОГИЧЕСКОЕ ИЛИ: |, XOR: ^, ЛОГИЧЕСКОЕ НЕ: ~
|
|||
|
|
c = a&b; // c = 0b...0101 & 0b...0011 = 0b...0001 = 1
|
|||
|
|
c = a|b; // c = 0b...0101 | 0b...0011 = 0b...0111 = 7
|
|||
|
|
c = a^b; // c = 0b...0101 ^ 0b...0011 = 0b...0110 = 6
|
|||
|
|
c = ~a; // зависит от числа байт в int. Так-то не знаем, но на x86_64 процессорах int это 4 байта. Тогда:
|
|||
|
|
// c = ! 0b 00000000_00000000_00000000_00000101 = 0b 11111111_11111111_11111111_11111010 = ?
|
|||
|
|
// Начиная с C23 (последнего стандартно) в языке регламентировано то, что 1 бит соответствует знаку -.
|
|||
|
|
// Тогда если все биты 1 - то получится -1, если первый бит 1 а остальные 0 - получится -2^{число битов -1}. 4 байта->32 бита -> -2^31
|
|||
|
|
// 0b 11111111_11111111_11111111_11111010 = 0b 11111111_11111111_11111111_11111111 - 0b...0101 = -1 - 5 = -6
|
|||
|
|
// По сути, для целых чисел ~x === -x-1
|
|||
|
|
// float устроены внутри себя гораздо сложнее, чем целочисленные типы, лучше с ними такого не делать
|
|||
|
|
|
|||
|
|
|
|||
|
|
// сдвиг влево/вправо: << и >>
|
|||
|
|
c = a << 1; // c = 0b...0101 << 1 = 0b...01010 = 10
|
|||
|
|
// по сути, для целых чисел x << y = x * 2^y
|
|||
|
|
c = a >> 1; // c = 0b...0101 >> 1 = 0b...010 = 2
|
|||
|
|
// по сути, для целых чисел x >> y = x / 2^y
|
|||
|
|
|
|||
|
|
// просто логические операторы. Тогда, с точки зрения C, false = 0, не false (т.е. true) = не 0:
|
|||
|
|
// ЛОГИЧЕСКОЕ И: &&, ЛОГИЧЕСКОЕ ИЛИ: ||, ЛОГИЧЕСКОЕ НЕТ: !
|
|||
|
|
c = a && b; // 1, т.к. оба истина
|
|||
|
|
c = 0 && a; // 0, т.к. есть ложь. При этом a даже не вычисляется (всё ради оптимизаций)
|
|||
|
|
c = 0 || 0; // 0, т.к. оба ложь
|
|||
|
|
c = a || 0; // 1, т.к. есть истина. Правое значение тоже не вычисляется
|
|||
|
|
c = !a; // 0, т.к. a - истина
|
|||
|
|
|
|||
|
|
// операторы сравнения
|
|||
|
|
c = a==b; // 0, т.к. a > b
|
|||
|
|
c = a!=b; // 1, т.к. a > b
|
|||
|
|
c = a>b; // 1, т.к. a > b
|
|||
|
|
c = a>=b; // 1, т.к. a > b
|
|||
|
|
c = a<b; // 0, т.к. a > b
|
|||
|
|
c = a<=b; // 0, т.к. a > b
|
|||
|
|
|
|||
|
|
float nan = 0.0/0.0; // за счёт '.' компилятор понимает, что 0.0 - это float, а не int
|
|||
|
|
float inf = 1.0/0.0;
|
|||
|
|
float negative_inf = -inf;
|
|||
|
|
float negative_zero = -1/0/inf;
|
|||
|
|
|
|||
|
|
c = nan==nan; // ложь. Аналогично с >= и <=
|
|||
|
|
c = nan!=nan; // истина
|
|||
|
|
c = negative_inf==inf; // ложь
|
|||
|
|
c = negative_zero==0.0; // истина
|
|||
|
|
c = 1.0/0.0 == 1.0/negative_zero; // ложь (т.к. negative_inf != inf)
|
|||
|
|
|
|||
|
|
// арифметические действия
|
|||
|
|
c = a+b;
|
|||
|
|
c = a-b;
|
|||
|
|
c = a%b; // остаток от деления. 5 % 3 = 2. При этом, почему-то, -5%3 = -2, а не 1
|
|||
|
|
с = a/b; // целочисленное деление. 5/3 = 1. При этом -5/3 = -1.
|
|||
|
|
// a == b*(a/b)+a%b (если b != 0)
|
|||
|
|
// для дробных чисел, конечно же, не выполняется, т.к. они связаны с неточными вычислениями.
|
|||
|
|
// возведения в степень нет
|
|||
|
|
|
|||
|
|
return 0;
|
|||
|
|
}
|