Files
C-examples/3variables/variables.c
2025-12-28 00:10:39 +03:00

93 lines
6.1 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}