Внимание! Сайт переезжает на http://computermuseum.igorb5ru.beget.tech
Показаны сообщения с ярлыком компилятор. Показать все сообщения
Показаны сообщения с ярлыком компилятор. Показать все сообщения

воскресенье, 4 декабря 2016 г.

Язык Си

Си — инструмент, острый, как бритва: с его помощью можно создать и элегантную программу, и кровавое месиво
Брайан У. Керниган
C (Си) — язык программирования разработанный в 1969-1973 годах в Bell Labs Кеном Томпсоном и Деннисом Ритчи. Создан как развитие языка B (Би) и был предназначен для ОС UNIX. С тех пор считается самым каноничным языком программирования.
Язык Си — компилируемый. Это значит что программа-компилятор переводит Си-программу в бинарный код, который затем выполняется напрямую процессором. Это дает прирост в скорости выполнения программного кода по сравнению с интерпретацией.

Программа

int main(){return 0;} //самая простая программа на Си, которая возвращает 0 операционной системе после своего запуска. 

Важно заметить, что все строки между фигурными скобками (которые ограничивают блоки операторов) должны заканчиваться точкой с запятой.
Особенность языка, его тогдашняя инновационность, заключалась в том, что код разделялся на функции. И это разделение удобно (в отличие от языка PL/M). И все функции программы будут вызываться из главной функции main, которая в программе должна быть обязательно.
Создать функцию просто: тип имя_функции(аргументы}{тело функции}. Появление вызова функции в программе должно идти после её описания (когда указывается тело функции), или же указать в начале файла все функции, которые у нас будут в программе.
Функция может возвращать значение определенного типа (оператором return) или же ничего не возвращать (тогда на месте типа пишут void и такая функция становится процедурой).

Переменные

Типы данных в Си приближены к процессору.
4 типа целых чисел:
  1. signed short int — короткое целое со знаком (2 байта)
  2. unsigned short int — короткое целое без знака
  3. signed long int или просто int — длинное целое со знаком (4 байта)
  4. unsigned long int — длинное целое без знака
Два типа с плавающей точкой:
  1. float — число с плавающей точкой (4 байта),
  2. double — число с двойной точностью (8 байт).
И несколько специфических типов данных:
  1. enum — перечисления,
  2. struct — структуры,
  3. union — объединение.
Существует символьный тип данных — char (1 байт). Строка в понятии языка, это массив из char'ов.
Типы автоматически не преобразуются один в другой, т. к. это потребовало бы дополнительных вливаний вычислений в код.
Конечно же можно создать массив однотипных данных. В том числе и неопределенного размера. И в отличие от BASIC нумерация элементов массива начинается с 0. Элементы локально-объявленного массива инициализировать нельзя, а глобального — можно.
Работа с переменной начинается с её объявления: int a. Объявление может происходить одновременно с инициализацией: int a=0;
Замечание: размеры в байтах указаны для архитектуры x86 и являются архитектуро-зависимыми.

Константы

\n — новая строка, \t — табуляция, \b — шаг назад, \r — возврат каретки, \\ - косая черта, \' - апостроф, \" - кавычки.

Операторы присваивания

= простое присваивание.
+= -= *= /= %= <<= >>= &= ^= |= хитрые присваивания. Их задача уменьшить количество действий с памятью.
Нельзя не сказать и о операторах ++ и --.

Арифметические операторы

  1. + - сложение
  2. - - вычитание
  3. * - умножение
  4. / - деление нацело
  5. % - остаток от деления нацело
  6. ~ побитовое НЕ
  7. & побитовое И
  8. | побитовое ИЛИ
  9. ^ побитовое исключающее ИЛИ

Операторы отношений

  1. == равенство
  2. != неравенство
  3. < > <= >= различные операторы отношения
Эти операторы возвращают 1 если сравнение истинно, 0 если ложно. Важно, что Си не понимает двойного сравнения (как и все остальные языки).

Логичесике операторы

  1. ! логическое НЕ
  2. && логическое И
  3. || логическое ИЛИ
Хотя есть мнение, что деление на логические и арифметические операторы условно. Об этом читать ниже.

Функции

if(условие) оператор1 else оператор2. Если условие истинно (не ноль), то выполняется оператор1, а если нет (условие 0) — то оператор2. Это позволяет проще записывать сравнения с нулем, например if(x!=0) <=> if(x) и if(x==0) <=> if(!x).
while(уловие) оператор1. Цикл выполняет оператор1 до тех пор, пока условие не ноль. for(оператор1; условие; оператор2). Сначала выполнится оператор1, затем будет выполняться оператор2 до тех пор, пока условие не станет ложным.
break используется для предварительного выхода из цикла.
Строго говоря, на этом встроенные функции языка Си исчерпываются. Да, функции ввода-вывода не являются стандартными.
printf(строка, список переменных). Функция форматированного вывода. Количество аргументов для функции переменно и зависит от того, сколько переменных вы хотите вывести. Вывод строки не вызовет никаких проблем: printf("Hello world!"). Чтобы вывести строку с переносом строки нужно написать на нужной позиции \n (new line), например printf("Kill\nall\nhumans\n"). А чтобы вывести значение переменной нужно приложить немного усилий: printf("%d", a). %d означает, что переменная, подготовленная к выводу, целочисленная. %s — строка, %d — целое число.
scanf(строка, переменные). Функция форматированного ввода, аналогична printf. В конец строки автоматически добавляется нулевой символ (\0).

Указатели

Механизм, который вызывает трепет уважения у понявших, ненависть у не понявших и пренебрежении у тех, кто до этого писал на ассемблере.
Например, нам в функции нам нужно изменить значение переданной переменной.
void set(int x){x=14;}
int main(){
 int a=88;
 set(a);
 printf("%d\n", a); //выведется 88
 return 0;
}

Это происходит и-за того, что в функцию передается копия значения переменной,а не она сама. Чтобы избежать этого, модифицируем программу таким образом:
void set(int *x){ //функция получает адрес переменной типа int
 *x=14; //и записывает по этому адресу 14
}
int main(){
 int a=88; set(&a); //передаем адрес на переменную
 printf("%d\n", a); //выведется 14
 return 0;
}

Механизм указателей позволяет быстро и энергоэффективно проворачивать хитрые операции, но это тема отдельной статьи.

Библиотеки

Библиотеки добавляют множество функций в систему языка. Причислим самые часто используемые:
  1. math.h — математическая библиотека содержит модуль, тригонометрические функции, арк-функции, гиперболический функции, логарифмы, возведение в степень и некоторыми другими.
  2. signals.h — библиотека работы с сигналами в ОС Unix.
  3. stdio.h — библиотека содержащая функции для функций стандартного ввода-вывода. Содержит функции работы с файлами (fopen, fclose, remove, rename), fgetc (получить символ), fgets (получить строку), fputc (записать символ), fputs (записать строку), getchar (получает символ со стандартного устройства ввода), gets (получает строку со стандартного устройства ввода), fprintf, fcanf (уже были обсуждены) и проч.
  4. stdlib.h — стандартная библиотека с функциями:
    1. преобразования типов (XtoY, например atoi — строка в целое число),
    2. генерации псевдослучайных чисел (rand, srand),
    3. выделения памяти (Xalloc, например malloc),
    4. контроль выполнения (exit — завершить программу, abort — экстренно завершить программу),
    5. сортировка (qsort) и проч.
  5. string.h — библиотека работы со строками содержит функции копирования, сравнения, конкатенации (дописывания, сложения строк), поиска символов, лексикографического сравнения, определения длины строки и проч.

Директивы компилятора

Директива компилятора начинается с символа # и означает некоторое действие, которое компилятор обязан выполнить, например #include имя_файла означает включить содержимое указанного файла в текущий. Таким образом функции, объявленные в этом, подключенном файле, становятся «видны» в нашей программе.
Другой важной директивой является #define строка значение. Компилятор ищет строку в файле и заменяет её на значение. Это позволяет легко выполнять требование отсутствия в коде «магических констант»: #define BIG_NUM 256.

Компиляторы

  1. GNU Compiler Collection включает компилятор Си. Знает все диалекты и может компилировать код под огромное количество платформ.
  2. MinGW — Минималистичный GNU для Windows. Содержит библиотеки WinAPI.
  3. MS C — старый компилятор от MS под DOS.
  4. TCC — маленький компилятор Си с возможностью интерпретации (!) Си-программ.

Диалекты

  1. K&RC (Си Крнигана и Ритчи). Опубликован вместе с книгой «Язык программирования Си» в 1978.
  2. ISO C или ANSI C. Стандарт языка разработанный ANSI в 1989. Например, теперь функция main должна возвращать хоть какое-то значение (не быть void).
  3. СC99. (легко догадаться до года - 1999) Некоторые добавления: возможность объявлять локальные переменные в любом месте (как в C++): for(int i=0; …) вместо int i; for(i=0; …), однострочные комментарии (как в C++).
  4. C++11. (2011 год, спасибо Кэп!) Введены современные мэйнстримовые фичи: многопоточность, юникод, и проч.

воскресенье, 15 ноября 2015 г.

Светлые идеи ООП

Введение


Мой друг объясняет это так. Когда заводят двигатель в машине, то поворачивают ключ. Никто же не лезет под капот и не замыкает провода в ручную?
Классы (а подход программирования, связанный с их созданием и активным использованием называется объектно-ориентированным программированием или ООП) сделаны для того, чтобы во время будущей разработки программисту было проще.
Например, нужно написать математическую программу (вот эта задача актуальна -- хороших мало), и программисты отдельно пишут классы для матриц, всяких хитрых чисел и прочего.
И с этими очень сложными классами работает очень простая (правда, по сравнению с кодом классов) функция или опять же класс.
Вообще слово «класс» - хреновое, в компьютерном английском оно значит то что надо, а в русском - непонятно дерьмо. Лучше бы называть это «объект», но всем как всегда... пофиг.
Представим, что мы инженер. И у нас есть класс - машина. Что мы можем позволить делать пользователю? Завести машину, залить топливо, воду, масло, еще чего-нибудь, сесть в неё, поехать, погрузить вещи, тещу. Это все «публичные функции» - то, что мы разрешаем делать всем с нашим объектом (классом) - «машина». Еще мы можем публично распространять данные о машине - марку, цвет, объем бака - это «публичные данные».
А то, что пользователю делать нельзя, нужно самой машине. К примеру, цикл простейшего двигателя внутреннего сгорания состоит из нескольких фаз: подача топлива, сжатие поршнем до возгорания, использование полученной энергии и выпуск газов. Вот такие функции называются «приватными», пользователю их вызывать не нужно.
class car{ //класс "автомобиль"
  int key;
public:
  car(string wanted); //конструктор
  ~car(); //деструктор

  string type; //тип машины
  string tank_volume; //объем бака
  bool start(int key); //завести
  void fuel(int volume); //заправить
  void drive(); //вести машину
};

Теперь, если мы захотим использовать наш автомобиль, надо будет создать автомобиль, сесть в него и поехать.
car first_car;
fisrt_car.start(1337);
fisrt_car.drive();

Конструктор и деструктор

Когда ты пишешь int a=48 компьютер из своих 4 Гб (или сколько там у тебя ОЗУ, %username%) выделяет место для хранения числа 48 (может быть 2 байта).
Когда ты пишешь класс, тебе тоже нужно место, где можно хранить свои данные. Для этого и создан конструктор. Чтобы выделить память под новое значение и туда еще может быть чего-нибудь записать.
У тебя 4 Гб памяти у компа. но на одну програму по умолчанию дается далеко не 4 Гб. И даже не 512 Мб. а что-то около 20 Мб. А если ты будешь создавать много-много объектов, то памяти начнет занимать все больше... и это грозит тем, что программа забъет всю отведенную ей память данными, которые ей быть может и не нужны.
Для этого и нужен деструктор - чтобы удалять уже ненужный хлам.
Замечание! В некоторых языка есть система, которая сама удаляет из памяти ненужные данные и работает сама по себе. называется она «уборкой мусора», правда о её эффективности ходят слухи и шутки.... Например, если бы в Java нормально работала уборка мусора, то она бы выкинула в корзину саму себя.
Конструктор и деструктор у разных классов могут быть внешне похожи, но работать совсем по разному.
car::car(string wanted){ //конструктор нашего автомобиля, хотя погодите-ка.. OH SHI
  type = wanted;
  key = generate_key(); //создаем ключ к автомобилю. считаем что такая функция есть
}
car::~car(){ //деструктор автомобиля
  delete(); //отправим его на переплавку
}

Перегрузка

Это понятие означает, что с разными данными мы работаем по разному, а называем эти действия одинаково. Разные действия выполняются при отправке электронного письма и отправке бумажного письма (кто-нибудь помнит о такой вещи?).

А теперь о грустном

Считается, что ООП увеличивает скорость разработки программ путем абстрагирования от конкретной реализации задачи, следовательно - решение меньшего числа подзадач, а посему - трата меньшего числа времени. А чем больше вы сделаете за меньший промежуток времени -- тем больше будет скорость. Но тут же появляется несколько проблем.
Электронно-вычислительная машина -- главная проблема. Да, ведь мы пишем программу для неё, а не для себя. Чем отдаленней исходный код от машины, тем больше труда приходится приложить компилятору (и программистам компилятора) или интерпретатору (о боже!) чтобы выполнить этот код. Таким образом, решение элементарных задач проходит через несколько слоёв абстракций (которые, возможно, и полезны при проектировании масштабных проектов), вместо того, чтобы сразу задействовать ресурсы вычислительный машины.
Компилятор (или интерпретатор). Как бы не были сложны и совершенны алгоритмы компиляторов (add eax, 0x1), они никогда не не сравнятся с силой человеческого ума, наличие которого безусловно повышает «уровень вхождения» в язык, избавляет от толп непрофессионалов-спекулянтов и переводит программирование из «ремесла» в искусство.
При написании объектно-ориентированного кода постоянно возникает следующая ситуация. Сначала разрабатывается и реализуется объектная модель применительно к задаче, затем необходимо спуститься на уровень ниже (методы класса) и реализовать его, а потом еще раз вернуться на объектный уровень.
Изобретенное ООП долго обходили стороной, но когда ЭВМ набрали мощности, псевдо-программисты прознали про перспективную область и ринулись туда породив «бум ООП», который не утихает до сих пор, разлагая умы начинающих программистов.