changes
This commit is contained in:
16
1hello_world/hello.c
Normal file
16
1hello_world/hello.c
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// объявление внешней функции puts, которая печатает строку str
|
||||||
|
int puts(char* str);
|
||||||
|
|
||||||
|
// функция main - главная функция
|
||||||
|
int main(){
|
||||||
|
// вызов функции puts
|
||||||
|
puts("Hello, World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Для компиляции нужно в терминале написать `tcc hello.c`
|
||||||
|
// Для запуска нужно в этом же терминале написать `hello.exe`
|
||||||
|
|
||||||
|
/*
|
||||||
|
"//" обозначают комментарии, они не влияют на то, какой будет программа
|
||||||
|
Также C поддерживает комментарии-блоки (как этот), но не поддерживает их как вложенные
|
||||||
|
*/
|
||||||
13
2exitcode/exitcode.c
Normal file
13
2exitcode/exitcode.c
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// Вывод в консоль, на самом деле, нетривиальная задача. Поэтому мы были вынуждены использовать внешнюю функцию puts в прошлом примере.
|
||||||
|
// Поэтому напишем программу, которая что-то делает, но без вывода в консоль
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
return 1+2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Для компиляции: `tcc exitcode.c`
|
||||||
|
// Для запуска: `exitcode.exe`
|
||||||
|
// Для того, чтобы увидеть результат, который вернула программа, в cmd нужно написать `echo %ERRORLEVEL%` сразу после предыдущей команды.
|
||||||
|
|
||||||
|
// Вообще, обычно main возвращает код статуса результата выполнения программы.
|
||||||
|
// Так 0 соответствует успешному выполнению, не 0 - коду какой-то ошибки (что-то подобное происходит на сайтах при показе ошибок 404 и т.д.)
|
||||||
92
3variables/variables.c
Normal file
92
3variables/variables.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
Ориентировочная ОС: Windows
|
Ориентировочная ОС: Windows
|
||||||
Ориентировочный текстовый редактор: Notepad++$^1$
|
Ориентировочный текстовый редактор: Notepad++$^1$
|
||||||
Ориентировочный компилятор: tcc$^2$
|
Ориентировочный компилятор: tcc$^2$
|
||||||
|
|
||||||
1: Спрашивайте лично/используйте интернет/другой редактор
|
1: Спрашивайте лично/используйте интернет/другой редактор
|
||||||
2: https://github.com/phoenixthrush/Tiny-C-Compiler/releases/tag/0.9.27-win64
|
2: https://github.com/phoenixthrush/Tiny-C-Compiler/releases/tag/0.9.27-win64 Советую добавить его в PATH$3$:
|
||||||
|
Изменение переменных среды текущего пользователя
|
||||||
|
PATH: добавить путь к папке, в которой лежит tcc.exe
|
||||||
|
После этого в консоли можно проверить, находится ли он в PATH, через команду
|
||||||
|
tcc -v
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
int puts(char *str);
|
|
||||||
|
|
||||||
int main(){
|
|
||||||
puts("Hello, World!");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user