Так, например, в аргументы параметрического макроса невозможно передать инициализацию массива, поскольку его элементы тоже разделяются запятой:#define array_of(type, array) (((type) []) (array)) int *a; a = array_of(int, {1, 2, 3}); // ошибка компиляции: // в макрос "array_of" передано 4 аргумента, но он принимает лишь 2Макроопределения часто используются для обеспечения совместимости с разными версиями библиотек, у которых изменился API, включая те или иные участки кода в зависимости от версии библиотеки. Для этих целей библиотеки часто предоставляют макроопределения с описанием своей версии, а иногда и макросы с параметрами для сравнения текущей версии с заданной в рамках препроцессора. Также макроопределения применяются для условной компиляции отдельных кусков программы, например для включения поддержки какого-либо дополнительного функционала. Макроопределения с параметрами широко используются в Си-программах для создания аналогов обобщённых функций. Ранее они также применялись для реализации встраиваемых функций, но начиная со стандарта С99 эта необходимость исчезла благодаря добавлению inline-функций. Однако в связи с тем, что макроопределения с параметрами функциями не являются, но вызываются аналогичным образом, по ошибке программиста могут возникать неожиданные проблемы, включая отработку только части кода из макроопределения и неправильные приоритеты выполнения операций. В качестве примера ошибочного кода можно привести макрос возведения числа в квадрат: #include <stdio.h> int main(void) { #define SQR(x) x * x printf("%d", SQR(5)); // всё верно, 5*5=25 printf("%d", SQR(5 + 0)); // предполагалось 25, но будет выведено 5 (5+0*5+0) printf("%d", SQR(4 / 3)); // всё верно, 1 (т. к. 4/3=1, 1*4=4, 4/3=1) printf("%d", SQR(5 / 2)); // предполагалось 4 (2*2), но будет выведено 5 (5/2*5/2) return 0; } В приведённом выше примере ошибкой является то, что содержимое аргумента макроса подставляется в текст как есть, без учёта приоритетов операций. В таких случаях необходимо использовать inline-функции либо явно расставлять приоритеты операций в выражениях, использующих параметры макроса, с помощью круглых скобок: #include <stdio.h> int main(void) { #define SQR(x) ((x) * (x)) printf("%d", SQR(4 + 1)); // верно, 25 return 0; } Программирование на Си Структура программы Модули Программа представляет собой набор файлов с кодом на языке Си, которые могут компилироваться в объектные файлы. Объектные файлы затем проходят этап компоновки друг с другом, а также со внешними библиотеками, в результате чего получается итоговый исполняемый файл или библиотека. Связь файлов друг с другом, равно как и с библиотеками, требует описания прототипов используемых функций, внешних переменных и необходимых типов данных в каждом файле. Такие данные принято выносить в отдельные заголовочные файлы, которые подключаются с помощью директивы #include в тех файлах, где требуется та или иная функциональность, и позволяют организовывать систему, похожую на систему модулей. Модулем в таком случае может выступать: набор отдельных файлов с исходным кодом, для которых представлен интерфейс в виде заголовочных файлов; объектная библиотека или её часть, с соответствующими заголовочными файлами; самодостаточный набор из одного или более заголовочных файлов (интерфейсная библиотека); статическая библиотека или её часть с соответствующими заголовочными файлами; динамическая библиотека или её часть с соответствующими заголовочными файлами. Поскольку директива #include лишь подставляет текст другого файла на этапе препроцессора, многократное подключение одного и того же файла может приводить к ошибкам этапа компиляции. Поэтому в таких файлах используется защита от повторного включения с помощью макрокоманд #define и #ifndef. Файлы исходного кода Текст файла исходного кода на языке Си состоит из набора глобальных определений данных, типов и функций. Глобальные переменные и функции, объявленные со спецификаторами static и inline, доступны только в пределах того файла, в котором они объявлены, либо при включении одного файла в другой через директиву #include. При этом функции и переменные, объявленные в заголовочном файле со словом static, будут создаваться заново при каждом подключении заголовочного файла к очередному файлу с исходным кодом. Глобальные переменные и прототипы функции, объявленные со спецификатором extern, считаются подключаемыми из других файлов. То есть их допускается использовать в соответствии с описанием; предполагается, что после сборки программы они будут связаны компоновщиком с оригинальными объектами и функциями, описанными в своих файлах. Глобальные переменные и функции, кроме static и inline, могут быть доступны из других файлов при условии их надлежащего объявления там со спецификатором extern. Переменные и функции, объявленные с модификатором static, также могут быть доступны в других файлах, но лишь при передаче их адреса по указателю. Объявления типов typedef, struct и union не могут импортироваться в других файлах. При необходимости использования в других файлах они должны быть там продублированы либо вынесены в отдельный заголовочный файл. То же самое относится и к inline-функциям. Точка входа программы Для исполняемой программы стандартной точкой входа является функция с именем main, которая не может быть статической и должна быть единственной в программе. Исполнение программы начинается с первого оператора функции main() и продолжается до выхода из неё, после чего программа завершается и возвращает операционной системе абстрактный целочисленный код результата своей работы. В переменную argc при вызове передаётся количество аргументов, переданных программе, включая и путь к самой программе, поэтому обычно переменная argc содержит значение не меньшее, чем 1. В переменную argv передаётся сама строка запуска программы в виде массива текстовых строк, последним элементом которого является NULL. Компилятор гарантирует, что на момент запуска функции main() все глобальные переменные в программе будут инициализированы. В качестве результата функция main() может вернуть любое целое число в диапазоне значений типа int, которое будет передано операционной системе или другому окружению в качестве кода возврата программы. Стандарт языка не определяет смысла кодов возврата. Обычно операционная система, где работают программы, имеет те или иные средства, позволяющие получить значение кода возврата и проанализировать его. Иногда существуют определённые соглашения о значениях этих кодов. Общим является соглашение о том, что нулевое значение кода возврата сигнализирует об успешном завершении программы, а ненулевое представляет собой код возникшей ошибки. Заголовочный файл stdlib.h определяет два общих макроопределения EXIT_SUCCESS и EXIT_FAILURE, которые соответствуют успешному и неуспешному завершению работы программы. Коды возврата также могут использоваться в рамках приложений, включающих в себя множество процессов, для обеспечения взаимодействия между этими процессами, в случае чего приложение само определяет смысловое значение для каждого кода возврата. Работа с памятью Модель памяти В Си предусмотрено 4 способа выделения памяти, которые определяют время жизни переменной и момент её инициализации. Все эти способы хранения данных пригодны в различных ситуациях и имеют свои преимущества и недостатки. Глобальные переменные не позволяют писать реентерабельные алгоритмы, а автоматическое выделение памяти не позволяет возвращать произвольную область памяти из вызова функции. Автоматическое выделение также не подходит для выделения больших объёмов памяти, поскольку может привести к порче стека или кучи. Динамическая память лишена этих недостатков, но имеет большие накладные расходы при её использовании и более сложна в использовании. Там, где это возможно, предпочтительным является автоматическое или статическое выделение памяти: такой способ хранения объектов управляется компилятором, что освобождает программиста от трудностей ручного выделения и освобождения памяти, как правило, служащего источником трудно отыскиваемых ошибок утечек памяти, ошибок сегментирования и повторного освобождения в программе. К сожалению, многие структуры данных имеют переменный размер во время выполнения программы, поэтому из-за того, что автоматически и статически выделенные области должны иметь известный фиксированный размер во время компиляции, очень часто требуется использовать динамическое выделение. Для автоматически выделяемых переменных с помощью модификатора register можно давать подсказку компилятору о необходимости быстрого доступа к ним. Такие переменные могут помещаться в регистры процессора. Из-за ограниченного количества регистров и возможных оптимизаций компилятора переменные могут оказаться в обычной памяти, но тем не менее из программы на них невозможно будет получить указатель. Модификатор register является единственным, который можно указывать в аргументах функций. Адресация памяти Язык Си унаследовал линейную адресацию памяти при работе со структурами, массивами и выделенными областями памяти. Стандарт языка также допускает выполнение операций сравнения над нулевым указателем и над адресами в рамках массивов, структур и выделенных областей памяти. Также допускается работа с адресом элемента массива, следующим за последним, что сделано для облегчения написания алгоритмов. Однако сравнение указателей адресов, полученных для разных переменных (или областей памяти) не должно осуществляться, так как результат будет зависеть от реализации конкретного компилятора. Представление в памяти Представление памяти программы зависит от аппаратной архитектуры, от операционной системы и от компилятора. Так, например, на большинстве архитектур стек растёт вниз, но существуют архитектуры, где стек растёт вверх. Граница между стеком и кучей может быть частично защищена от переполнения стека специальной областью памяти. А расположение данных и кода библиотек может зависеть от параметров компиляции.


wikipedia

Стандарт Си абстрагируется над реализацией и позволяет писать переносимый код, однако понимание устройства памяти процесса помогает в отладке и написании безопасных и отказоустойчивых приложений. Типовое представление памяти процесса в Unix-подобных ОС При запуске программы из исполняемого файла в оперативную память импортируются инструкции процессора (машинный код) и инициализированные данные. В то же время в старшие адреса импортируются аргументы командной строки (доступные в функции main() со следующей сигнатурой во втором аргументе int argc, char ** argv) и переменные окружения. Область неинициализированных данных содержит глобальные переменные (в том числе, объявленные как static), которые не были проинициализированы в программном коде. Такие переменные по умолчанию инициализируются нулями после старта программы. Область инициализированных данных — сегмент данных — тоже содержит глобальные переменные, но в эту область попадают те переменные, которым было задано начальное значение. Неизменяемые данные, включающие в себя переменные, объявленные с модификатором const, строковые литералы и другие составные литералы, помещаются в сегмент текста программы. Сегмент текста программы содержит также исполняемый код и доступен только на чтение, поэтому попытка изменения данных из этого сегмента приведёт к неопределённому поведению в виде ошибки сегментации. Область стека предназначена для размещения данных, связанных с вызовом функций, и локальных переменных. Перед каждым запуском функции стек увеличивается для размещения в нём аргументов, передаваемых в функцию. В ходе своей работы функция может размещать в стеке локальные переменные и выделять в нём память под массивы переменной длины, а некоторые компиляторы предоставляют также средства выделения памяти в рамках стека посредством вызова alloca(), который не входит в стандарт языка. После завершения работы функции стек уменьшается до того значения, которое было перед вызовом, однако этого может не происходить при некорректной работе со стеком. Память, выделенная динамически, предоставляется из кучи. Немаловажной деталью является наличие случайного отступа между стеком и верхней областью, а также между областью инициализированных данных и кучей. Делается это в целях безопасности, например, для предотвращения встраивания в стек других функций. Динамически подключаемые библиотеки и отображения файлов с файловой системы находятся между стеком и кучей. Обработка ошибок В Си отсутствуют какие-либо встроенные механизмы контроля ошибок, но существует несколько общепринятых способов их обработки средствами языка. В общем виде практика обработки ошибок языка Си в отказоустойчивом коде вынуждает писать громоздкие, часто повторяющиеся конструкции, в которых алгоритм совмещён с обработкой ошибок. Маркеры ошибок и errno В языке Си активно используется специальная переменная errno из заголовочного файла errno.h, в которую функции заносят код ошибки, возвращая при этом значение, являющееся маркером ошибки. Для проверки результата на ошибки результат сравнивают с маркером ошибки, и, если они совпадают, то можно проанализировать код ошибки, сохранённый в errno, для корректировки работы программы или вывода отладочного сообщения. В стандартной библиотеке стандарт зачастую лишь определяет возвращаемые маркеры ошибок, а выставление errno зависит от конкретной реализации. В качестве маркеров ошибок обычно выступают следующие значения: -1 для типа int в случаях, когда отрицательный диапазон результата не используется; -1 для типа ssize_t (POSIX); (size_t) -1 для типа size_t; (time_t) -1 при использовании некоторых функций для работы со временем; NULL для указателей; EOF при потоковой работе с файлами; ненулевой код ошибки. Практика возвращения маркера ошибки, вместо кода ошибки, хоть и экономит количество передаваемых в функции аргументов, но в ряде случаев приводит к ошибкам в результате человеческого фактора. Например, программистами часто игнорируется проверка результата типа ssize_t, а сам результат используется дальше в вычислениях, что приводит к трудно уловимым ошибкам, если возвращается -1. Ещё сильнее способствует появлению ошибок возврат в качестве маркера ошибки корректного значения, что также вынуждает программиста делать больше проверок, а соответственно и писать больше однотипного повторяющегося кода. Такой подход практикуется в потоковых функциях, работающих с объектами типа FILE *: маркером ошибки является значение EOF, одновременно являясь и маркером конца файла. Поэтому по EOF иногда приходится проверять поток символов как на конец файла с помощью функции feof(), так и наличие ошибки с помощью ferror(). При этом некоторые функции, которые могут вернуть EOF по стандарту не обязаны выставлять errno. Отсутствие единой практики обработки ошибок в стандартной библиотеке приводит к появлению собственных способов обработки ошибок и комбинированию часто используемых способов в сторонних проектах. Например, в проекте systemd совместили идеи возвращения кода ошибки и числа -1 в качестве маркера — возвращается отрицательный код ошибки. А в библиотеке GLib ввели в практику возвращение в качестве маркера ошибки значение булева типа, в то время как подробная информация об ошибке помещается в специальную структуру, указатель на которую возвращается через последний аргумент функции. Схожее решение использует проект Enlightenment, в котором в качестве маркера тоже используется булев тип, но информация об ошибке возвращается по аналогии со стандартной библиотекой — через отдельную функцию, которую необходимо проверять, если был возвращён маркер. Возврат кода ошибки Альтернативой маркерам ошибок является возвращение кода ошибки напрямую, а результата работы функции — через аргументы по указателю. По такому пути пошли разработчики стандарта POSIX, в функциях которого принято возвращать код ошибки в виде числа типа int. Однако возвращение значения типа int явно не даёт понять, что возвращается именно код ошибки, а не маркер, что может вести к ошибкам, если результат таких функций будет проверяться на значение -1. В расширении K стандарта C11 представлен специальный тип errno_t для хранения кода ошибки. Существуют рекомендации использовать именно этот тип в пользовательском коде для возвращения ошибок, а если он не предоставлен стандартной библиотекой, то объявлять его самостоятельно:#ifndef __STDC_LIB_EXT1__ typedef int errno_t; #endifТакой подход, помимо повышения качества кода, избавляет от необходимости использования errno, что позволяет делать библиотеки с реентерабельными функциями без необходимости подключения дополнительных библиотек, таких как POSIX Threads для правильного определения errno. Ошибки в математических функциях Более сложной является обработка ошибок в математических функциях из заголовочного файла math.h, в которых могут возникать 3 типа ошибок: выход за пределы диапазона входных значений; получение бесконечного результата для конечных входных данных; выход результата за пределы диапазона используемого типа данных. Предотвращение двух из трёх типов ошибок сводится к проверкам входных данных на область допустимых значений. Однако предсказать выход результата за пределы типа крайне сложно. Поэтому стандартом языка предусмотрена возможность анализа математических функций на ошибки. Начиная со стандарта C99 такой анализ возможен двумя способами, в зависимости от значения, хранимого в макросе math_errhandling. Если выставлен бит MATH_ERRNO, то переменную errno необходимо предварительно сбросить в 0, а после вызова математической функции — проверить на ошибки EDOM и ERANGE. Если выставлен бит MATH_ERREXCEPT, то возможные математические ошибки предварительно сбрасываются функцией feclearexcept() из заголовочного файла fenv.h, а после вызова математической функции —тестируются с помощью функции fetestexcept(). При этом способ обработки ошибок определяется конкретной реализацией стандартной библиотеки и может отсутствовать совсем. Поэтому в платформонезависимом коде может потребоваться проверка результата сразу двумя способами, в зависимости от значения math_errhandling. Освобождение ресурсов Как правило возникновение ошибки требует завершения работы функции с возвращением индикатора ошибки. Если в функции ошибка может возникнуть в разных её частях, требуется освобождать ресурсы, выделенные в ходе её работы, чтобы предотвратить утечки. Хорошей практикой освобождения ресурсов считается их чистка в обратном порядке перед возвратом из функции, а в случае ошибок — освобождение в обратном порядке после основного return. В отдельные части такого освобождения можно сделать переход с помощью оператора goto. Подобный подход позволяет вынести не связанные с реализуемым алгоритмом участки кода за пределы самого алгоритма, повышая читабельность кода, и схож с работой оператора defer из языка программирования Go. Пример освобождения ресурсов приведён ниже, в разделе примеров. Для освобождения ресурсов в рамках программы предусмотрен механизм обработчиков выхода из программы. Обработчики назначаются с помощью функции atexit() и исполняются как по завершении функции main() через оператор return, так и по исполнению функции exit(). При этом обработчики не исполняются по функциям abort() и _Exit(). В качестве примера освобождения ресурсов по завершении программы можно привести освобождение памяти, выделенной под глобальные переменные. Несмотря на то, что память так или иначе освобождается по завершении работы программы операционной системой, и допускается не освобождать ту память, которая требуется на протяжении всей работы программы, явное освобождение предпочтительнее, так как облегчает поиск утечек памяти сторонними средствами и уменьшает шанс на возникновение утечек памяти в результате ошибки: #include <stdio.h> #include <stdlib.


> int numbers_count; int *numbers; void free_numbers(void) { free(numbers); } int main(int argc, char **argv) { if (argc < 2) { exit(EXIT_FAILURE); } numbers_count = atoi(argv[1]); if (numbers_count <= 0) { exit(EXIT_FAILURE); } numbers = calloc(numbers_count, sizeof(*numbers)); if (!numbers) { perror("Ошибка выделения памяти под массив"); exit(EXIT_FAILURE); } atexit(free_numbers); // ... работа с массивом numbers // Здесь будет автоматически вызван обработчик free_numbers() return EXIT_SUCCESS; } Недостатком данного подхода является то, что формат назначаемых обработчиков не предусматривает передачу произвольных данных в функцию, что позволяет создавать обработчики только для глобальных переменных. Примеры программ на Си Минимальная программа на Си Минимальная программа на Си, не требующая обработки аргументов, имеет следующий вид: int main(void){} Допускается не писать оператор return у функции main(). В таком случае, согласно стандарту, функция main() возвращает 0, исполняя все обработчики, назначенные на функцию exit(). При этом подразумевается, что программа успешно завершилась. Hello, world! Программа Hello, world! приведена ещё в первом издании книги «Язык программирования Си» Кернигана и Ритчи: #include <stdio.h> int main(void) // Не принимает аргументы { printf("Hello, world!\n"); // '\n' - новая строка return 0; // Удачное завершение программы } Эта программа печатает сообщение «Hello, world!» на стандартном устройстве вывода. Обработка ошибок на примере чтения файла Многие функции языка Си могут вернуть ошибку, не выполнив требуемых от них действий. Ошибки требуется проверять и правильно на них реагировать, в том числе часто требуется пробрасывать ошибку из функции на уровень выше для анализа. При этом функцию, в которой произошла ошибка, можно делать реентерабельной, в таком случае по ошибке функция не должна изменять входные или выходные данные, что позволяет безопасно перезапускать её после исправления ошибочной ситуации. В примере реализована функция чтения файла на языке Си, однако она требует соответствия функций fopen() и fread() стандарту POSIX, иначе они могут не выставлять переменную errno, что сильно усложняет как отладку, так и написание универсального и безопасного кода. На платформах, не соответствующих POSIX, поведение данной программы будет неопределённым в случае ошибки. Освобождение ресурсов по ошибкам находится за основным алгоритмом для повышения читабельности, а переход осуществляется с помощью goto. #include <errno.h> #include <stdio.h> #include <stdlib.h> // Определяем тип для хранения кода ошибки, если он не определён #ifndef __STDC_LIB_EXT1__ typedef int errno_t; #endif enum { EOK = 0, // значение errno_t при успешном завершении }; // Функция чтения содержимого файла errno_t get_file_contents(const char *filename, void **contents_ptr, size_t *contents_size_ptr) { FILE *f; f = fopen(filename, "rb"); if (!f) { // В POSIX fopen() выставляет errno по ошибке return errno; } // Получаем размер файла fseek(f, 0, SEEK_END); long contents_size = ftell(f); if (contents_size == 0) { *contents_ptr = NULL; *contents_size_ptr = 0; goto cleaning_fopen; } rewind(f); // Переменная для хранения возвращаемого кода ошибки errno_t saved_errno; void *contents; contents = malloc(contents_size); if (!contents) { saved_errno = errno; goto aborting_fopen; } // Читаем содержимое файла целиком по указателю contents size_t n; n = fread(contents, contents_size, 1, f); if (n == 0) { // Не проверяем на feof(), т. к. буферизировано после fseek() // В POSIX fread() выставляет errno по ошибке saved_errno = errno; goto aborting_contents; } // Возвращаем выделенную память и её размер *contents_ptr = contents; *contents_size_ptr = contents_size; // Секция освобождения ресурсов по успешному завершению cleaning_fopen: fclose(f); return EOK; // Отдельная секция для освобождения ресурсов по ошибке aborting_contents: free(contents); aborting_fopen: fclose(f); return saved_errno; } int main(int argc, char **argv) { if (argc < 2) { return EXIT_FAILURE; } const char *filename = argv[1]; errno_t errnum; void *contents; size_t contents_size; errnum = get_file_contents(filename, &contents, &contents_size); if (errnum) { char buf[1024]; const char *error_text = strerror_r(errnum, buf, sizeof(buf)); fprintf(stderr, "%s\n", error_text); exit(EXIT_FAILURE); } printf("%.*s", (int) contents_size, contents); free(contents); return EXIT_SUCCESS; } Средства разработки Компиляторы Некоторые компиляторы идут в комплекте с компиляторами других языков программирования (включая C++) или являются составной частью среды разработки программного обеспечения. GNU Compiler Collection (GCC) полностью поддерживает стандарты C99 и C17 (C11 с исправлениями). Также поддерживает расширения GNU, защиту кода с помощью санитайзеров и набор дополнительных возможностей, в том числе атрибуты. Clang также полностью поддерживает стандарты C99 и C17. Разрабатывается во многом совместимым с компилятором GCC, в том числе поддерживает расширения GNU и защиту кода санитайзерами. BDS C Borland C++ C++ Builder Digital Mars DJGPP Intel C++ compiler LCC Microsoft Visual Studio MinGW Open Watcom Oracle Solaris Studio Pelles C Portable C Compiler Tiny C Compiler Topspeed JPI C Реализации стандартной библиотеки Несмотря на то, что стандартная библиотека входит в стандарт языка, её реализации идут отдельно от компиляторов. Поэтому стандарты языка, поддерживаемые компилятором и библиотекой, могут различаться. Открытая библиотека glibc является основной во многих дистрибутивах GNU/Linux, поддерживает стандарты C11 и POSIX.1-2008, а также предоставляет набор исправлений и дополнительных возможностей от GNU. Открытая библиотека musl задумывалась в качестве более легковесной замены для glibc, используется как библиотека по умолчанию в дистрибутиве Alpine Linux, Void Linux. Библиотека CRT от Microsoft поддерживает стандарт C99, поставляется как компонент в составе Windows 10. Интегрированные среды разработки CLion полностью поддерживает C99, но поддержка С11 — частичная, сборка основана на CMake. Code::Blocks — свободная кроссплатформенная интегрированная среда разработки для языков Си, C++, D, Fortran. Поддерживает более двух десятков компиляторов. С компилятором GCC доступен Си всех версий от C90 до C17. Eclipse — свободная интегрированная среда разработки, поддерживающая язык Си стандарта С99. Имеет модульную архитектуру, что даёт возможность подключения поддержки разных языков программирования и дополнительных возможностей. Доступен модуль для интеграции с Git, однако отсутствует интеграция с CMake. KDevelop — свободная интегрированная среда разработки, поддерживающая некоторые особенности языка Си из стандарта C11. Позволяет управлять проектами, использующими разные языки программирования, включая C++ и Python, поддерживает систему сборки CMake. Имеет встроенную поддержку Git на уровне работы с файлами и настраиваемое форматирование исходного кода для разных языков. Microsoft Visual Studio лишь частично поддерживает стандарты C99 и C11, поскольку ориентируется на разработку под C++, однако имеет встроенную поддержку CMake. Средства модульного тестирования Поскольку язык Си не предоставляет средств для безопасного написания кода, а многие элементы языка способствуют появлению ошибок, написание качественного и отказоустойчивого кода можно гарантировать только с помощью создания автоматизированных тестов. Для упрощения такого тестирования существуют различные реализации сторонних библиотек модульного тестирования. Библиотека Check предоставляет фреймворк для тестирования программного кода на языке Си в общепринятом стиле xUnit. Среди возможностей можно упомянуть запуск тестов в отдельных процессах через fork(), что позволяет распознавать в тестах ошибки сегментирования, а также даёт возможность задавать максимальное время исполнения отдельных тестов. Библиотека Google Test также предоставляет тестирование по принципам xUnit, но предназначена для тестирования кода на языке C++, что позволяет её использовать для тестирования кода и на языке Си. Также поддерживает изолированное тестирование отдельных частей программы. Одним из достоинств библиотеки является разделение макросов тестирования на утверждения и ошибки, что может облегчить отладку кода. Существует также много других систем для тестирования кода на Си, таких как AceUnit, GNU Autounit, cUnit и других, но они либо не осуществляют тестирование в изолированных окружениях, либо предоставляют мало возможностей, либо перестали развиваться. Средства отладки По проявлениям ошибок не всегда можно сделать однозначный вывод о проблемном месте в коде, однако локализовать проблему часто помогают различные средства отладки. Gdb — интерактивный консольный отладчик для различных языков, в том числе и для Си. Valgrind является средством динамического анализа кода, может выявлять ошибки в коде непосредственно во время выполнения программы. Поддерживает выявление: утечек, обращений в неинициализированную память, обращений по неверным адресам (в том числе переполнение буфера). Также поддерживает исполнение в режиме профилирования с помощью профайлера callgrind. KCacheGrind — графический интерфейс для визуализации результатов профилирования, полученных с помощью профайлера callgrind. Компиляторы на динамические языки и платформы Иногда, в целях переноса тех или иных библиотек, функций и инструментов, написанных на Си, в иную среду, требуется компиляция Си-кода на язык более высокого уровня или в код виртуальной машины, предназначенной для такого языка. Следующие проекты предназначены для этих целей: Emscripten — компилятор из LLVM-байт-кода (например, полученный из C++) в JavaScript. (старое название — Alchemy) — компилятор из Си/C++ в ActionScript Virtual Machine (AVM2). Позволяет использовать Си-библиотеки в Flash- и Adobe AIR-приложениях. Clue — компилятор из ANSI Си в Lua, JavaScript, Perl, Java, Common Lisp. AMPC — компилятор из Си в виртуальную машину Java.


Дополнительные инструменты Также для Си существуют и другие инструменты, облегчающие и дополняющие разработку, включая статические анализаторы и утилиты для форматирования кода. Статический анализ помогает выявлять потенциальные ошибки и уязвимости. А автоматическое форматирование кода упрощает организацию совместной работы в системах контроля версий, минимизируя конфликты из-за стилевых правок. Cppcheck — статический анализатор кода для языков Си и C++ с открытыми исходными текстами, иногда выдаёт ложные срабатывания, которые можно подавлять специально оформленными комментариями в коде. Clang-format — утилита командной строки для форматирования исходного кода согласно заданному стилю, который может указываться в специально оформленном файле конфигурации. Обладает множеством параметров и несколькими встроенными стилями. Разрабатывается в рамках проекта Clang. Утилиты Indent и GNU Indent также предоставляют форматирование кода, но параметры форматирования задаются в виде опций командной строки. Область применения Язык широко применяется при разработке операционных систем, на уровне прикладного интерфейса операционных систем, во встраиваемых системах, а также для создания высокопроизводительного или критического в плане обработки ошибок кода. Одной из причин широкого распространения для программирования на низком уровне является возможность писать кроссплатформенный код, который может по-разному обрабатываться на разном оборудовании и на разных операционных системах. Возможность писать высокопроизводительный код обеспечивается за счёт полной свободы действий программиста и отсутствия строгого контроля со стороны компилятора. Так, например, на языке Си написаны первые реализации языков Java, Python, Perl и PHP. При этом во многих программах наиболее требовательные к ресурсам части принято писать на языке Си. Ядро программы Mathematica написано на Си, а MATLAB, изначально написанный на Фортране, был переписан на Си в 1984 году. Также Си иногда используется как промежуточный язык при компиляции более высокоуровневых языков. Например, по такому принципу работали первые реализации языков C++, Objective-C и Go, — код, написанный на этих языках, транслировался в промежуточное представление на языке Си. Современными языками, работающими по такому же принципу, являются язык Vala и Nim. Ещё одной областью применения языка Си являются приложения реального времени, которые требовательны по части отзывчивости кода и времени его исполнения. Такие приложения должны начинать исполнение действий в жёстко ограниченных временных рамках, а сами действия должны укладываться в определённый временной промежуток. В частности, стандарт POSIX.1 предоставляет набор функций и возможностей для создания приложений реального времени, однако поддержка жёсткого реального времени должна быть также реализована и со стороны операционной системы. Языки-потомки Язык Си был и остаётся одним из самых распространённых языков программирования в течение более чем сорока лет. Естественно, что его влияние можно проследить в той или иной мере во многих более поздних языках. Тем не менее среди языков, достигших определённого распространения, прямых потомков у Си немного. Часть языков-потомков надстраивает Си дополнительными средствами и механизмами, добавляющими поддержку новых парадигм программирования (ООП, функциональное программирование, обобщённое программирование и пр.). К таким языкам относятся, прежде всего, C++ и Objective-C, а опосредованно — их потомки Swift и D. Также известны попытки улучшить Си, исправив его наиболее существенные недостатки, но сохранив его привлекательные черты. Среди них можно упомянуть исследовательский язык Cyclone (и его потомок Rust). Иногда оба направления развития объединяются в одном языке, примером может служить Go. Отдельно необходимо упомянуть о целой группе языков, которые в большей или меньшей мере унаследовали базовый синтаксис Си (использование фигурных скобок в качестве ограничителей блоков кода, описание переменных, характерные формы операторов for, while, if, switch с параметрами в скобках, комбинированные операции ++, , +=, -= и другие), из-за чего программы на этих языках имеют характерный внешний вид, ассоциирующийся именно с Си. Это такие языки как Java, JavaScript, PHP, Perl, AWK, C#. В действительности структура и семантика этих языков сильно отличается от Си, и обычно они предназначены для тех сфер применения, где оригинальный Си никогда не использовался. C++ Язык программирования C++ был создан из Си и унаследовал его синтаксис, дополнив его новыми конструкциями в духе языков Simula-67, Smalltalk, Modula-2, Ada, Mesa и Clu. Основными дополнениями стали поддержка ООП (описание классов, множественное наследование, полиморфизм, основанный на виртуальных функциях) и обобщённого программирования (механизм шаблонов). Но помимо этого в язык внесено множество самых различных дополнений. На данный момент C++ является одним из наиболее распространённых языков программирования в мире и позиционируется как язык общего назначения с уклоном в системное программирование. Изначально C++ сохранял совместимость с Си, которая была заявлена как одно из преимуществ нового языка. Первые реализации C++ просто переводили новые конструкции в чистый Си, после чего код обрабатывался обычным Си-компилятором. Для сохранения совместимости создатели C++ отказались от исключения из него некоторых часто критикуемых особенностей Си, вместо этого создав новые, «параллельные» механизмы, которые рекомендуется применять при разработке нового кода на C++ (шаблоны вместо макроопределений, явное приведение типов вместо автоматического, контейнеры стандартной библиотеки вместо ручного динамического выделения памяти и так далее). Однако в дальнейшем языки развивались независимо, и сейчас Си и C++ последних выпущенных стандартов являются лишь частично совместимыми: не гарантируется успешная компиляция программы на Си компилятором C++, а в случае успеха нет гарантии, что откомпилированная программа будет работать правильно. Особенно неприятны некоторые тонкие семантические различия, которые могут приводить к разному поведению одного и того же кода, синтаксически корректного для обоих языков. Например, символьные константы (символы, заключённые в одинарные кавычки) имеют тип int в Си и тип char в C++, так что объём памяти, занимаемый такими константами, в разных языках различается. Если программа чувствительна к размеру символьной константы, она будет работать по-разному, будучи откомпилирована трансляторами Си и C++. Подобные различия затрудняют написание программ и библиотек, которые могли бы нормально компилироваться и работать одинаково и в Си и в C++, что, конечно, запутывает тех, кто программирует на обоих языках. Среди разработчиков и пользователей как Си, так и C++ есть сторонники максимального сокращения различий между языками, что объективно принесло бы ощутимую пользу. Существует, однако, и противоположная точка зрения, согласно которой совместимость не особенно важна, хоть и полезна, и усилия по уменьшению несовместимости не должны препятствовать улучшению каждого языка в отдельности. Objective-C Ещё одним вариантом расширения Си объектными средствами является язык Objective-C, созданный в 1983 году. Объектная подсистема была заимствована из Smalltalk, причём все элементы, связанные с этой подсистемой, реализованы в собственном синтаксисе, достаточно резко отличающемся от синтаксиса Си (вплоть до того, что в описании классов синтаксис объявления полей противоположен синтаксису описания переменных в Си: сначала пишется имя поля, затем его тип). В отличие от C++, Objective-C является надмножеством классического Си, то есть сохраняет совместимость с исходным языком; правильная программа на Си является правильной программой на Objective-C. Другим существенным отличием от идеологии C++ является то, что Objective-C реализует взаимодействие объектов путём обмена полноценными сообщениями, тогда как в C++ реализована концепция «отправка сообщения как вызов метода». Полноценная обработка сообщений является значительно более гибкой, к тому же она естественным образом сочетается с параллельными вычислениями. Objective-C, а также его прямой потомок Swift являются одними из самых популярных на платформах, поддерживаемых Apple. Проблемы и критика Язык Си уникален с той точки зрения, что именно он стал первым языком высокого уровня, всерьёз потеснившим ассемблер в разработке системного программного обеспечения. Он остаётся языком, реализованным на максимальном количестве аппаратных платформ, и одним из самых популярных языков программирования, особенно в мире свободного программного обеспечения. Тем не менее язык имеет множество недостатков, он с момента появления подвергается критике многих специалистов. Общая критика Язык весьма сложен и наполнен опасными элементами, которые очень легко использовать неправильно. Своей структурой и правилами он никак не поддерживает программирование, нацеленное на создание надёжного и удобного в сопровождении программного кода, напротив, рождённый в эпоху прямого программирования под различные процессоры, язык способствует написанию небезопасного и запутанного кода. Многие профессиональные программисты склонны считать, что язык Си — мощный инструмент для создания элегантных программ, но в то же время с его помощью можно создавать крайне некачественные решения. Из-за различных допущений в языке программы могут компилироваться со множественными ошибками, что часто приводит к непредсказуемому поведению программы. Современные компиляторы предоставляют опции для статического анализа кода, но даже они не способны выявить все возможные ошибки. Результатом неграмотного программирования на Си могут стать уязвимости программного обеспечения, что может сказаться на безопасности его использования. У Си высокий порог вхождения.


Спецификация его занимает более 500 страниц текста, которые необходимо изучить полностью, так как для создания безошибочного и качественного кода приходится учитывать многие неочевидные особенности языка. Например, автоматическое приведение операндов целочисленных выражений к типу int может давать трудно предсказуемые результаты при использовании бинарных операторов: unsigned char x = 0xFF; unsigned char y = (~x | 0x1) >> 1; // Интуитивно здесь ожидается 0x00 printf("y = 0x%hhX\n", y); // Будет выведено 0x80, если sizeof(int) > sizeof(char) Недостаточное понимание подобных нюансов может приводить к появлению многочисленных ошибок и уязвимостей. Ещё одним фактором, увеличивающим сложность освоения Си, является отсутствие обратной связи от компилятора: язык даёт программисту полную свободу действий и позволяет компилировать программы с явными логическими ошибками. Всё это затрудняет использование Си в обучении в качестве первого языка программирования Наконец, за более чем 40 лет существования язык успел несколько устареть, и в нём достаточно проблематично использовать многие современные приёмы и парадигмы программирования. Недостатки отдельных элементов языка Примитивная поддержка модульности В синтаксисе Си нет модулей и механизмов их взаимодействия. Файлы исходного кода компилируются раздельно и должны включать прототипы импортируемых из других файлов переменных, функций и типов данных. Для этого используется включение заголовочных файлов через макроподстановку #include. В случае нарушения соответствия между файлами кода и заголовочными файлами могут возникать как ошибки этапа компоновки, так и всевозможные ошибки времени исполнения: от порчи стека и кучи до ошибок сегментирования. Поскольку директива #include лишь подставляет текст одного файла в другой, включение большого количества заголовочных файлов приводит к тому, что многократно возрастает фактический объём кода, попадающего на компиляцию, что является причиной относительно низкой скорости работы компиляторов языка Си. Необходимость согласования описаний в основном модуле и заголовочных файлах затрудняет сопровождение программы. Предупреждения вместо ошибок Стандарт языка даёт программисту большую свободу действий и тем самым — высокие шансы на допущение ошибок. Многое из того, что чаще всего нельзя делать, дозволено языком, и компилятор в лучшем случае выдаёт предупреждения. Хотя современные компиляторы позволяют переводить все предупреждения в класс ошибок, эта возможность используется редко, гораздо чаще предупреждения игнорируются, если программа работает удовлетворительно. Так, например, до стандарта C99 вызов функции malloc без подключения заголовочного файла stdlib.h мог привести к порче стека, поскольку в отсутствие прототипа функция вызывалась как возвращающая тип int, тогда как фактически она возвращала тип void* (ошибка возникала, когда размеры типов на целевой платформе различались). Но даже при этом выдавалось всего лишь предупреждение. Отсутствие контроля инициализации переменных Автоматически и динамически создаваемые объекты по умолчанию не инициализируются и после создания содержат значения, оставшиеся в памяти от ранее находившихся там объектов. Такое значение полностью непредсказуемо, оно меняется от одной машины к другой, от запуска к запуску, от вызова функции к вызову. Если программа из-за случайного пропуска инициализации использует такое значение, то результат будет непредсказуемым и может проявиться не сразу. Современные компиляторы пытаются диагностировать эту проблему статическим анализом исходного кода, хотя в общем случае статическим анализом данную проблему решить крайне сложно. Для выявления данных проблем на этапе тестирования в ходе исполнения программы могут использоваться дополнительные инструменты: Valgrind и MemorySanitizer. Отсутствие контроля над адресной арифметикой Источником опасных ситуаций служит совместимость указателей с числовыми типами и возможность использования адресной арифметики без строгого контроля на этапах компиляции и исполнения. Это даёт возможность получить указатель на любой объект, включая исполняемый код, и обратиться по этому указателю, если только механизм защиты памяти системы этому не воспрепятствует. Неправильное использование указателей может порождать неопределённое поведение программы и приводить к серьёзным последствиям. К примеру, указатель может быть неинициализированным или, в результате неверных арифметических операций, указывать в произвольное место памяти. На одних платформах работа с таким указателем может вызвать принудительную остановку программы, на других это может привести к порче произвольных данных в памяти; последняя ошибка опасна тем, что её последствия непредсказуемы и могут проявиться в произвольный момент времени, в том числе намного позже момента собственно ошибочного действия. Доступ к массивам в Си также реализован посредством адресной арифметики и не предполагает средств проверки корректности обращения к элементам массива по индексу. Например, выражения a[i] и i[a] идентичны и просто транслируются к виду *(a + i), а проверка на выход за границы массива не проводится. Обращение по индексу, превышающему верхнюю границу массива, приводит к обращению к данным, размещённым в памяти после массива, что называют переполнением буфера. Когда подобное обращение происходит ошибочно, оно может привести к непредсказуемому поведению программы. Нередко данная особенность используется в эксплоитах, используемых для нелегального доступа к памяти другого приложения или памяти ядра операционной системы. Побуждающая к ошибкам динамическая память Системные функции для работы с динамически выделяемой памятью не обеспечивают контроля за правильностью и своевременностью её выделения и освобождения, соблюдение правильного порядка работы с динамической памятью полностью возлагается на программиста. Его ошибки, соответственно, могут приводить к обращению по некорректным адресам, к преждевременному освобождению либо к утечке памяти (последнее возможно, например, если разработчик забыл вызвать free() или вызывающую free() функцию, когда это требовалось). Одной из частых ошибок является отсутствие проверок результата работы функций выделения памяти (malloc(), calloc() и прочие) на NULL, в то время как память может не выделиться, если её не хватает, или если был запрошен слишком большой объём, например, из-за приведения числа -1 , полученного в результате каких-либо ошибочных математических операций, к беззнаковому типу size_t, с последующими операциями над ним. Ещё одной проблемой системных функций работы с памятью является неспецифицированное поведение при запросе выделения блока нулевого размера: функции могут вернуть как NULL, так и действительное значение указателя, в зависимости от конкретной реализации. Некоторые конкретные реализации и сторонние библиотеки предоставляют такие средства, как подсчёт ссылок и слабые ссылки, умные указатели, а также ограниченные формы сборки мусора, но все эти средства не являются стандартными, что, естественно, ограничивает их применение. Неэффективные и небезопасные строки Для языка стандартными являются нуль-терминированные строки, соответственно все стандартные функции работают именно с ними. Это решение приводит к значительной потере эффективности за счёт малозначительной экономии памяти (по сравнению с явным хранением размера): вычисление длины строки (функция strlen()) требует обхода в цикле всей строки от начала до конца, копирование строк также сложно оптимизировать из-за наличия терминирующего нуля. Из-за необходимости добавлять к данным строки терминирующий нуль становится невозможным эффективное получение подстрок в виде срезов и работа с ними как с обычными строками; выделение частей строк и манипуляции с ними обычно требуют ручного выделения и освобождения памяти, что дополнительно повышает вероятность ошибки. Нуль-терминированные строки являются частым источником ошибок. Даже стандартные функции обычно не выполняют проверки на размер целевого буфера и могут не добавлять в конце строки нулевой символ, не говоря уже о том, что он может быть не добавлен или затёрт из-за ошибки программиста.. Небезопасная реализация функций с переменным числом аргументов Поддерживая функции с переменным числом аргументов, Си не содержит ни средств определения числа и типов фактических параметров, переданных такой функции, ни механизма безопасного доступа к ним. Информирование функции о составе фактических параметров лежит на программисте, а для доступа к их значениям необходимо отсчитать правильное количество байтов от адреса последнего фиксированного параметра в стеке либо вручную, либо пользуясь набором макросов va_arg из заголовочного файла stdarg.h. При этом необходимо учитывать работу механизма автоматического неявного повышения типов при вызове функций, согласно которому целочисленные типы аргументов размером менее int приводятся к int (или unsigned int), а float приводится к double. Ошибка в вызове или в работе с параметрами внутри функции проявится только во время исполнения программы, приводя к непредсказуемым последствиям, от чтения неверных данных до порчи стека. При этом стандартным средством форматированного ввода-вывода являются именно функции с переменным числом параметров (printf(), scanf() и другие), не способные проверить соответствие списка аргументов строке формата. Многие современные компиляторы проводят такую проверку для каждого их вызова, генерируя предупреждения при обнаружении несоответствия, однако в общем случае подобная проверка невозможна, так как каждая функция с переменным числом аргументов обрабатывает этот список по-своему. Невозможно статически проконтролировать даже все вызовы функции printf(), поскольку строка формата может создаваться в программе динамически. Отсутствие унификации обработки ошибок Синтаксис Си не включает специального механизма обработки ошибок. Стандартная библиотека поддерживает лишь простейшие средства: переменная (в случае POSIX — макрос) errno из заголовочного файла errno.


Аре́с или Аре́й (, микен. a-re) — в древнегреческой мифологии — бог войны. Входит в состав двенадцати олимпийских богов, сын Зевса и Геры. В отличие от Афины Паллады — богини честной и справедливой войны, — Арес, отличаясь вероломством и хитростью, предпочитал войну коварную и кровавую, войну ради самой войны. В произведениях Гомера можно встретить отождествление Ареса с войной и смертоносным оружием. Спутницы Ареса — богиня раздора Эрида и кровожадная Энио. Его кони, дети одной из эриний и Борея, носили имена: Пламя, Шум, Ужас, Блеск. Атрибутами бога считались собаки, коршун, горящий факел и копьё. Изображался Арес обычно в виде могучего и зрелого воина в доспехах с мечом в руке и шлемом на голове. В римской мифологии ему соответствует Марс. Происхождение Первоначально считалось, что Гера родила Ареса от прикосновения к волшебному цветку. В более поздних мифах Арес выступал как сын Зевса, который называл его самым ненавистным из всех богов и утверждал, что не будь Арес его родным сыном, он бы давно отправил его в Тартар, туда, где томятся потомки небесного бога Урана. Имеются свидетельства о его негреческом, фракийском происхождении. Софокл называет его рождённым во Фракии. Арес упоминается с микенской эпохи; имя существовавшего в то же время бога войны Эниалия позже стало эпитетом Ареса. Характеристики В античной литературе можно встретить упоминания о том, что Арес был любовником самой красивой из богинь — Афродиты, иногда даже называются дети, которые были рождены от этого союза: Эрот, Антерос, Гармония, Гимерос, Фобос (страх) и Деймос (ужас). Из-за своих отрицательных качеств Арес с большим трудом утвердился среди остальных олимпийских богов, поэтому в его образе явственно прослеживаются следы напластования различных эпох. Некогда в течение 13 месяцев (лунного года) заточён в медной амфоре, либо в глиняном чане. Его пленили на время Алоады. Сам Арес освободил захваченного в плен Сизифом бога смерти Танатоса. Арес был возлюбленным богини Афродиты. Об их любви и нарушении Афродитой супружеской верности очень часто упоминается в античной мифологии. В битве за Пилос был ранен Гераклом. Также Геракл ранил его, когда убил Кикна. Арес участвовал в Троянской войне на стороне троянцев и был побеждён Афиной. Сын финикийского царя Агенора Кадм, основавший Фивы в Беотии, убил посвящённого Аресу дракона. Потомство Ареса От союза Ареса и Афродиты родились Эрот (любовь), Антерос (страсть, ненависть), Пофос (бог любовной тоски), Фобос (страх), Деймос (ужас) и Гармония, а также Гимерос. Также его дочерью была Энио. Потомство: Алкиппа. От Агравлы. Алкон. Амазонки. От нимфы Гармонии или Афродиты. Аскалаф и Иалмен. От Астиохи. Аэроп. От Аэропы. Мифический царь Тегеатиды (версия). Бистон и Диомед фракиец. От Кирены. Дракон в Фивах, убитый Кадмом. От эринии Тильфосы. Дриант из Калидона. Дриант фракиец. Евен, Мол, Пилос и Фестий. От Демоники или Демодики. Иксион (версия). Ипполита (она же Антиопа) и Пенфесилея. От Отреры. Ифит и Токсей. От Антиохи (версия). Кикн. От Пирены или Пелопии. Лик. Царь Ливии. Ликаон (неясно). Ликург фракиец (версия). Меланипп. От Тритии. Мелеагр. От Алфеи. Мерион (версия). Миний (версия). Нис мегарец (версия). Оксил. От Протогении. Парфенопей. От Аталанты (версия). Порфаон (версия). Ромул и Рем. От Сильвии или Эмилии. Терей. От Бистониды. Тидей. От Перибеи. Титаресий. Фавн (версия). Флегий. От Дотиды или Хрисы. Фракс. Фрасса. От Терины. Халиб. Эагр (версия). Эномай. От Астерии (она же Стеропа или Астеропа) или Гарпины}. Эрифион (Евритион). некий сын (лакуна в рукописи Гигина). От Леодоки. Его дети: (от неизвестных матерей) Меланиппа. Сватался к Персефоне. Его возлюбленной была Эос. Убитые Аресом Адонис Галиррофий Мимант(гигант) Пелор(гигант) Перифант(сын Охесия) Окружение Ареса Спутницами Ареса были богиня раздора Эрида и кровожадная Энио. Пироэйс — название звезды Ареса (планеты Марс). Названа так от страстной любви Ареса к Афродите. Эпитеты и отождествления Ареса Гермес. В микенскую эпоху эпитет Ареса: e-ma-a2 a-re-ja (Гермес Арес). Кандаон. Также имя Ареса. Мамерт. Эпитет Ареса. Эниалий (Арес Эниалий). Эпитет Ареса. Ареса отождествляют с италийским (римским) Марсом. Ему поклонялись в Египте (отождествлялся с Гором). В литературе и искусстве Ему посвящены VIII гимн Гомера и LXV орфический гимн. Примечания Литература Древнегреческие боги Боги войны Боги по алфавиту Двенадцать богов Олимпа Зевс Гера Боги планеты Марс


Арара́т может означать: Арарат — библейская (масоретская) огласовка названия государства Урарту. Имя Арарат () — армянское мужское имя. География Арарат (, , , — Ârârât) — вулканический массив, лежащий по правому берегу среднего течения реки Аракс, Турция, близ границы с Арменией. Арарат () — область в Армении. Арарат () — город в области Арарат в Армении. Арарат () — село в области Арарат в Армении. Арарат () — город в штате Виктория, Австралия. Арарат — упразднённый в 1996 году посёлок в Хасынском районе Магаданской области России. Арарат — упразднённый в 1973 году хутор в Степновском районе Ставропольского края России. Арарат — горный хребет в центральной части юга Приморского края; часть горной системы Сихотэ-Алинь. Арарат — гора в Хакасии, Россия. Арарат — река на юго-западе штата Виргиния и северо-западе штата Северная Каролина в США, приток реки Ядкин. История Республика Арарат — курдское государственное образование с 1927 по 1930 год Айрарат () — одна из областей Великой Армении Айраратское царство — древнее государство на территории Армянского нагорья Спорт «Арарат» () — иранский баскетбольный клуб «Арарат» (Тегеран). «Арарат» () — многоцелевой стадион в районе Ванак города Тегеран Другое Арарат () — марка армянского коньяка, выпускаемого ЕКЗ. «Арарат» (ЕКВВК АРАРАТ) — один из производителей армянского коньяка. Горы Араратские — место, в котором, согласно Книге Бытия (Бытие 8:4), остановился Ноев ковчег после потопа. Арарат () (2002) — фильм Атома Эгояна, посвященный геноциду армян. Арарад (Арарат, ) — армянская ежедневная газета (Бейрут). Официальное издание Социал-демократической партии Гнчакян. Арарат () — аэропорт в городе Арарат, штат Виктория, Австралия. Арарат — железнодорожная станция в одноимённом городе, расположенная на участке Масис — Ерасх. Арарат ФМ — популярная в Армении молодёжная радиостанция, вещающая на частоте 90.7 МГц. «Арарат» — гекбот Каспийской флотилии Российской империи, участник Персидского похода 1722—1723 годов. См. также Монрой Арарат, Жорди Примечания


Плея́ды ( ) — в древнегреческой мифологии группа из семи нимф-сестёр: Алкиона, Келено, Майя, Меропа, Астеропа (у Арата — Стеропа), Тайгета и Электра. Дочери титана Атланта от его супруги океаниды Плейоны имели брата Гиаса и сестёр Гиад. По отцу плеяд именовали Атлантиды (), Додониды (, в Додоне, где и происходили основные события сказания) и Нисиады () по роли нянек и учителей маленького Диониса. У римлян они назывались Вергилии ( — «Склоняющиеся»). Спутницы Артемиды, её эскорт. Впоследствии были превращены Зевсом в звёзды, образовавшие скопление Плеяды, и стали рассматриваться как небесные нимфы. Содержание мифов Согласно мифу, охотник Орион стал преследовать сестёр Плеяд. Плеяды обратились с мольбой о защите к богам. Чтобы защитить их, Зевс превратил их в голубок, которые обязаны были носить Зевсу амброзию (Додонское сказание). Когда голуби пролетали мимо сталкивающихся плавучих утёсов Планктов, одна из голубок погибала, и Зевс оживлял её (вариант — заменял новой). Однако это не помогло избавиться от Ориона — он не прекратил своих преследований. Тогда Зевс превратил Плеяд в звёзды и поместил их на небо в виде одноимённого астеризма в созвездии Телец, а Орион в наказание за свою дерзость тоже был превращён в группу звёзд и помещён на небо в виде созвездия Орион недалеко от Плеяд. Вышло так, что теперь Орион обречён до скончания веков безуспешно преследовать Плеяд по небосклону. Согласно другому мифу Плеяды оказались на небе после суицида. Один вариант суицида: Плеяды, охваченные горем по поводу гибели их брата Гиаса и сестёр Гиад, покончили с собой и затем были взяты на небо и превращены в созвездие. По другой версии они покончили с собой, огорчённые участью своего отца Атланта, обречённого вечно подпирать небесный свод. Именование Происхождение названия Плеяды имеет несколько версий. По одной из них, оно происходит от имени их матери, Плейоны. По ЭСБЕ, оно происходит от — голубки, иногда воспроизводится от — плыть как связанное с мореходной навигацией: Плеяды — довольно яркие звёзды, и были хорошо известны древним мореходам, которые часто использовали их как путеводные. Происхождение от (мореходствовать, путешествовать) объясняется тем, что звёзды Плеяды наблюдаются по ночам в районе Средиземного моря с середины мая по начало ноября — период активных торговых путешествий в античные времена. Плеяды (астеризм) считались покровительницами моряков, а их восхождение весной считалось началом наиболее благоприятного периода для навигации. «Радостно парус напряг Одиссей и, попутному ветру Вверившись, поплыл. Сидя на корме и могучей рукою Руль обращая, он бодрствовал; сон на его не спускался Очи, и их не сводил он с Плеяд, с нисходящего поздно в море Воота» Связь с богами Все Плеяды, кроме Меропы, связываются родственными узами с богами: например, старшая из них, наиболее выделяемая, Майя, родила от Зевса Гермеса, и лишь Меропа единственная вышла замуж за смертного (потому в созвездии, стыдясь своего поступка, она светит слабее остальных). Соединившись со знатными героями и богами, Плеяды стали прародительницами многих героев и богов Древней Греции. Эпитеты Местом происхождения Плеяд указывается гора Килини в Аркадии, в связи с чем ещё один их эпитет — «горные». У поэта Симонида Плеяды имеют эпитет — «с фиалковыми локонами», также у него встречается их эпитет Плеяды небесные. Источники Литература Псевдо-Аполлодор. Мифологическая библиотека III 10, 1 Катастеризмы Атлант Артемида Мифы Аркадии


Аполлон — в древнегреческой мифологии — бог света, а также вдохновения (искусств, музыки и поэзии), предводитель муз. Аполлон Бельведерский — известная статуя бога Аполлона, находящаяся в Ватикане. Аполлон (переносн.) — хорошо сложенный красивый мужчина. Насекомые Аполлоны — род высокогорных дневных бабочек семейства парусников. Аполлон — крупная дневная бабочка семейства парусников. Астрономия Аполлоны — группа астероидов. (1862) Аполлон — астероид в Солнечной системе. Аполлон — кратер на Луне. Астронавтика «Аполлон» — космическая программа США: «Аполлон» — серия космических кораблей США. «Аполлон-1» «Аполлон-2» «Аполлон-3» «Аполлон-4» «Аполлон-5» «Аполлон-6» «Аполлон-7» — первый пилотируемый полет серии «Аполлон». «Аполлон-8» — в результате полёта люди впервые достигли окрестностей другого небесного тела, Луны, и вышли на окололунную орбиту. «Аполлон-9» «Аполлон-10» «Аполлон-11» — люди впервые в истории совершили посадку на поверхность другого небесного тела — Луны. «Аполлон-12» «Аполлон-13» — из летавших к Луне пилотируемых кораблей — единственный, на котором в полёте произошла серьёзная авария. «Аполлон-14» «Аполлон-15» «Аполлон-16» «Аполлон-17» — на нём состоялся последний на данный момент пилотируемый полёт на Луну, шестая высадка людей на Луну. «Аполлон-18» «Аполлон-19» «Аполлон-20» «Аполлон (ЭПАС)» — космический корабль «Аполлон», совершивший полёт по совместной советско-американской программе «Союз — Аполлон». Художественные фильмы «Аполлон-13» — фильм 1995 года. «Аполлон 18» — американский псевдодокументальный фильм ужасов. Документальные фильмы «Аполлон-17. Последние люди на Луне» — американский документальный фильм 2010 года, посвящённый последнему полёту в рамках программы «Аполлон». Литература «Аполлон» — журнал, издававшийся в России с 1909 по 1917, а также с 1993 по 1998 годы. «Аполлон» — сатирический рассказ Аркадия Аверченко 1910 года о журнале «Аполлон»; текст в Викитеке: «Аполлон» (Аверченко). «Аполлон-77» — литературный альманах, изданный в 1977 в Париже Михаилом Шемякиным. Спортивные клубы «Аполлон» — кипрский профессиональный баскетбольный клуб из города Лимасол. См. также Аполлон-18 Apollo (значения) Мост Аполлон — мост через реку Дунай в городе Братислава Театр «Аполлон» Аполлоническое и дионисийское


PBEM (от , ) — разновидность онлайн-игр через интернет, где в качестве протокола для обмена данными игры используется электронная почта (e-mail, netmail, QWK и т. п.). Представляют собой пошаговые игры различной направленности, в основном — стратегические или ролевые игры. В качестве классического примера PBEM-игры можно привести шахматы по переписке. История Игры по переписке появились ещё во времена обычной почтовой связи, назывались они тогда PBM. С развитием техники и технологий связи, игры стали вестись по электронной почте, что значительно ускорило игровой процесс, кроме того позволило воспользоваться программным обеспечением для автоматической обработки игровой ситуации. Программы позволили привлечь к играм больше людей и сделать игру красочнее и нагляднее. Дальнейший шаг в развитии игр по переписке наблюдается в наши дни, это SMS-игры и MMORPG. На сегодняшний день для игр посредством электронной почты распространены два обозначения — PBEM (Play By Electronic Mail) и PBeM (Play By e-Mail). Некоторая разница в написании аббревиатуры сохраняет однозначность определения данного вида игр. Игровой процесс Обмен игровыми данными может происходить непосредственно между игроками (как в случае шахмат по переписке), если игроков несколько, то обработкой данных занимается посредник — человек гейм-мастер или игровой сервер, который отсылает участникам сведения об их текущем положении и получает приказы (описание хода) участников по почте. У игроков может быть специальная программа-клиент, которая обрабатывает отчёт сервера, может рисовать карту событий, принимать команды игрока на дальнейшие действия и формировать приказ. Ссылки PBEM.h1.ru FAQ по Civilization 3 PBEM Типы сетевых игр


Атомарная формула, элементарная формула или просто атом, в математической логике — простейший случай логической формулы; формула, которую нельзя расчленить на подформулы. Простейшим случаем атомов являются формулы, задающие отношения. Например утверждение «x больше 3» описывается атомом БОЛЬШЕ(x,3), где предикат БОЛЬШЕ истинен, когда первый аргумент больше второго. Аналогично записав «x любит y» как ЛЮБИТ(x, y), можно представить предложение «Саша любит Дашу», как ЛЮБИТ(Саша,Дашу). В логике первого порядка атомы также могут включать в себя функциональные символы. Общий вид атома в этом случае таков: , где — предикатный символ арности , а — термы. Например, если ОТЕЦ(x) означает «отец человека x», предложение «Ваня любит своего отца» можно представить атомом ЛЮБИТ(Ваня, ОТЕЦ(Ваня)). См. также Логика первого порядка Логический атомизм Математическая логика


О предикатах в виноделии см. вина с предикатом Предика́т ( «заявленное, упомянутое, сказанное») — это утверждение, высказанное о субъекте. Субъектом высказывания называется то, о чём делается утверждение. Предикат в программировании — выражение, использующее одну или более величину с результатом логического типа. Далее в этой статье слово предикат используется в значении высказывательной формы. Определение Предика́т (-местный, или -арный) — это функция с множеством значений (или {ложь, истина}), определённая на множестве . Таким образом, каждый набор элементов множества характеризуется либо как «истинный», либо как «ложный». Предикат можно связать с математическим отношением: если кортеж принадлежит отношению, то предикат будет возвращать на нём 1. В частности, одноместный предикат определяет отношение принадлежности некоторому множеству. Предикат — один из элементов логики первого и высших порядков. Начиная с логики второго порядка, в формулах можно ставить кванторы по предикатам. Предикат называют тождественно-истинным и пишут: если на любом наборе аргументов он принимает значение . Предикат называют тождественно-ложным и пишут: если на любом наборе аргументов он принимает значение . Предикат называют выполнимым, если хотя бы на одном наборе аргументов он принимает значение . Так как предикаты принимают только два значения, то к ним применимы все операции булевой алгебры, например: отрицание, импликация, конъюнкция, дизъюнкция и т. д. Примеры Обозначим предикатом отношение равенства («»), где . В этом случае предикат будет принимать истинное значение для всех равных и . Более житейским примером может служить предикат ПРОЖИВАЕТ для отношения « проживает в городе на улице » или ЛЮБИТ для « любит » для и принадлежащих , где множество — это множество всех людей. Предикат — это то, что утверждается или отрицается о субъекте суждения. Операции над предикатами Предикаты, так же, как высказывания, принимают два значения: истинное и ложное, поэтому к ним применимы все операции логики высказываний. Рассмотрим применение операций логики высказываний к предикатам на примерах одноместных предикатов. Логические операции Конъюнкцией двух предикатов A(x) и B(x) называется новый предикат , который принимает значение «истина» при тех и только тех значениях х из Т, при которых каждый из предикатов принимает значение «истина», и принимает значение «ложь» во всех остальных случаях. Множеством истинности Т предиката является пересечение множеств истинности предикатов A(x) — T1 и B(x) — T2, то есть T = T1 ∩ T2. Например: A(x): «x — чётное число», B(x): «x кратно 3». A(x) B(x) — «x — чётное число и x кратно 3». То есть предикат «x делится на 6». Дизъюнкцией двух предикатов A(x) и B(x) называется новый предикат , который принимает значение «ложь» при тех и только тех значениях x из Т, при которых каждый из предикатов принимает значение «ложь» и принимает значение «истина» во всех остальных случаях. Областью истинности Т предиката является объединение областей истинности предикатов A(x) — Т1 и B(x) — Т2, то есть Т = Т1 ⋃ Т2. Отрицанием предиката A(x) называется новый предикат ¬A(x), который принимает значение «истина» при тех и только тех значениях x из T, при которых предикат A(x) принимает значение «ложь», и принимает значение «ложь», если A(x) принимает значение «истина». Множеством истинности предиката x X является дополнение T' к множеству T в множестве X. Импликацией предикатов A(x) и B(x) называется новый предикат , который является ложным при тех и только тех значениях x из T, при которых A(x) принимает значение «истина», а B(x) — значение «ложь», и принимает значение «истина» во всех остальных случаях. Читают: «Если A(x), то B(x)». Например. A(x): «Натуральное число x делится на 3». B(x): «Натуральное число x делится на 4», можно составить предикат: «Если натуральное число x делится на 3, то оно делится и на 4». Множеством истинности предиката является объединение множества T2 — истинности предиката B(x) и дополнения к множеству T1 истинности предиката A(x). Кванторные операции Квантор всеобщности Квантор существования Квантор существования по переменной 1 См. также Исчисление предикатов Непредикативность Определяющий предикат Предикатив Литература Математическая логика


Бе́ршадь () — город в Винницкой области Украины. Входит в Гайсинский район. До 2020 года был административным центром Бершадского района. Географическое положение Находится на реке Дохна (бассейн Южного Буга). История Бершадь известна с 1459 года как обнесённая земляным валом крепость на южной границе Великого княжества Литовского. После Люблинской унии 1569 года — в составе Брацлавского воеводства Речи Посполитой. После начала восстания Хмельницкого в 1648 году Бершадь стала сотенным городом Уманского полка, но после подписания Андрусовского мира в 1667 году отошла к Речи Посполитой. В 1672 году город был захвачен войсками Османской империи, в 1699 году возвращён Речи Посполитой. 1793—1917 После второго раздела Речи Посполитой в 1793 году Бершадь вошла в состав Российской империи. В 1795 году стала местечком Ольгопольского уезда Подольской губернии (в это время здесь насчитывалось 668 дворов). В начале 1880 года здесь насчитывалось 4627 жителей, действовали винокуренный завод, сахарный завод и низшая школа. В 1891 году здесь насчитывалось 7 тыс. жителей и 1150 дворов, В 1897 году евреи в Бершади составляли более трех четвертей всего населения; в 1910 году в Бершади проживало 7400 евреев, и это составляло 61% от общего числа жителей. Кроме евреев, там жили украинцы, поляки, греки, но их дома находились, в основном, за пределами местечка. Действовали винокуренный завод, сахароваренный завод, кожевенный завод, кирпичный завод, черепичный завод, две водяные мельницы, одноклассное народное училище, аптека, православная церковь, старообрядческая часовня, римско-католическая часовня, синагога и 6 еврейских молелен. 1918—1991 В январе 1918 года в Бершади была провозглашена Советская власть, однако вскоре селение оккупировали австро-немецкие войска (которые оставались здесь до ноября 1918 года). В дальнейшем город оказался в зоне боевых действий гражданской войны и власть здесь несколько раз менялась. В 1923 году здесь были созданы сельскохозяйственные артели «Колос» и «Серп». В ходе Великой Отечественной войны 29 июля 1941 года Бершадь оккупировали немецко-румынские войска и она была включена в состав Транснистрии. Оккупационные власти устроили здесь еврейское гетто. Румынские власти создали на территории города гетто, которое занимало 12 переулков. Евреи разместились в 337 домах. Осенью 1941 года к местным евреям присоединились 20 тыс. евреев, депортированных из Буковины и Бессарабии. В результате, гетто оказалось перенаселенным. Евреи вынуждены были ютиться по 20 и более человек в комнате. Бершадское гетто было одним из самых крупных в румынской Транснистрии. Зима 1941—1942 годов оказалась самым сложным периодом для узников. В гетто вспыхнула эпидемия тифа, которая почти вдвое сократила население. По воспоминаниям очевидцев, по территории гетто каждый день ездила повозка, собиравшая трупы. Румынские власти использовали евреев на принудительных работах по заготовке дров, строительству дорог, а еврейские ремесленники производили одежду для оккупантов. С 1942 года румынской жандармерией командовал Георге Попеску, который облегчил страдания узников. В разгар эпидемии тифа он наладил поставки средств гигиены в гетто и разрешил местным жителям торговать с узниками. Вскоре, за подобные меры Попеску был уволен. Но с 1942 года оккупационные власти разрешили румынским евреям помогать депортированным. В результате, в гетто появились аптека, инфекционная больница, столовая и детский дом. С конца 1941 года в гетто действовало несколько подпольных групп. В декабре 1942 года часть подпольщиков присоединилась к партизанскому отряду имени Ленина. В 1943 году благодаря действиям подпольщиков был организован побег 900 узников. В январе—феврале 1944 года оккупанты расстреляли часть руководства гетто, но благодаря удачному стечению обстоятельств, к моменту освобождения Бершади в марте 1944 года в ней в живых остались 9,2 тыс. узников гетто. Из них 2,2 тыс. были местными евреями. Часть выживших вернулась в Румынию. 14 марта 1944 года в ходе Уманско-Ботошанской наступательной операции посёлок освободили части 2-го Украинского фронта. До войны в Бершади было три больших синагоги, из которых одна двухэтажная, построенная более 250 лет тому назад, сохранилась и по сегодняшний день, правда стоит она в аварийном состоянии, и почти некому в ней молиться, сейчас в Бершади остались всего три еврейские семьи. В декабре 1966 года посёлок городского типа Бершадь стал городом районного подчинения. В 1969 году численность населения составляла 11,8 тыс. человек, здесь действовали сахарный комбинат, спиртовой комбинат, маслодельный завод, завод сухого молока, завод металлических изделий, мебельная фабрика и швейная фабрика. В 1978 году здесь действовали сахарный комбинат, спиртовой комбинат, молочноконсервный комбинат, комбинат хлебопродуктов, завод металлоизделий, мебельная фабрика, швейная фабрика, райсельхозтехника, медицинское училище, три общеобразовательных школы, музыкальная школа, спортивная школа, три лечебных учреждения, Дом культуры, четыре библиотеки, два кинотеатра, пять клубов и краеведческий музей. В январе 1989 года численность населения составляла , в это время основой экономики являлись электротехнический завод и предприятия пищевой промышленности. После 1991 В мае 1995 года Кабинет министров Украины утвердил решение о приватизации находившихся в городе электротехнического завода, АТП-10527, АТП-10567, сахарного завода, райсельхозтехники, райсельхозхимии и ПМК № 233, в июле 1995 года было утверждено решение о приватизации Бершадского межрайонного строительно-монтажного предприятия № 2. В декабре 2010 года был признан банкротом комбинат хлебопродуктов и началась процедура его ликвидации. На 1 января 2013 года численность населения составляла 13 160 человек. Транспорт В городе расположена станция узкоколейной железной дороги Рудница — Голованевск. История еврейской общины В 1765 году в Бершади жило 438 евреев, в 1787 году — 650, в 1818 году — 3370, в 1897 году — 6603 (74,3 % от всего населения), в 1910 году — 7400 (60,7 %), в 1939 году — 4271 (74 %), в 1959 году — около 2,2 тыс., в 1970 году — около 1,8 тыс. (15,8 %) в 1979 году — около 1,5 тыс. (11,9 %). Община пострадала во время восстания Богдана Хмельницкого и гражданской войны - евреи массово уничтожались погромщиками, сжигались синагоги и книги, во время Второй Мировой войны от фашистов и их пособников погибли большинство еврейских жителей города и завезенных румынских евреев, в созданном оккупантами гетто. В 1990-е годы большинство евреев иммигрировало в Израиль и США. В 1998 в Бершади жило 180 евреев, в 2001 году 70. В 1900 году город населяло около 4,5 тысяч евреев, тогда как общее население составляло ок. 7 тыс. Количество еврейских мастеров доходило до 500. Во владении еврейской общины были три большие синагоги и шесть молельных домов. В середине девятнадцатого века Бершадь славилась еврейскими ткачами талита. К концу столетия спрос на талит сократился, и промышленность пошла на убыль, что привело к эмиграции большинство ткачей в США. Известные уроженцы, жители Бешер-Белинский, Леонид Борисович (05.02.1926 — 2015/16) — главный инженер Северного рудоуправления и директор Южного рудоуправления Навоийского ГМК, лауреат Государственной премии СССР. Миха-Иосиф Бердичевский (1865-1921), родившийся в семье бершадского раввина Моше Ааарона, ученика и последователя Рафаэля. Вобрав в себя черты бершадского хасида, Миха отличался огненным темпераментом, не признающим отдыха. После окончания ешивы он уехал учиться в Германию и Швейцарию, изучал еврейскую философию и иудаизм, окончил университет, получил звание доктора философии. В этот период он был приверженцем философии Ницше с его почитанием культа силы. Но позднее Миха Иосиф отвернулся от философии Ницше и приблизился к ценностям еврейской жизни, к идишкайту. Бердичевский в своих произведениях высоко чтил героев еврейской истории, тех, кто во всех поколениях вел борьбу за свободу и справедливость еврейского народа. Умер Бердичевский в 1921 году в возрасте 56 лет, его литературное наследие составило 25 томов на иврите и несколько книг на идиш. Он оказал значительное влияние на своих современников в конце XIX - начале XX столетия. Его смерть была вызвана трагической гибелью отца и брата во время страшного погрома в местечке Дубово Киевской губернии от рук банды украинского атамана Козакова. Отцу в момент гибели было 88 лет. Жизнь самого Михи Бердичевского оборвалась в момент, когда его творческие силы достигли расцвета. Примечания Литература Berszad // Słownik geograficzny Królestwa Polskiego i innych krajów słowiańskich. — Warszawa : Filip Sulimierski i Władysław Walewski, Tom XV, cz. 1 (Abablewo — Januszowo), 1900. Ссылки Бершадь ua. Інформаційний портал Портал Бершадського району сайт Бершадь Фото-альбом м. Бершадь, 5000 фото Бершаді та Бершадського району Форум міста Бершадь Шанхай-Бершадь. Старые фотографии бершадского «Шанхая» Города Винницкой области Населённые пункты Бершадского района Бывшие еврейские местечки Украины


«Тависуплеба» (, «Свобода») — государственный гимн Грузии, один из главных государственных символов Грузии, наряду с флагом и гербом, с апреля 2004 г. Музыка взята из двух опер Захария Палиашвили (1871—1933) — «Даиси» («Сумерки») и «Абесалом и Этери», автор текста — современный грузинский поэт Давид Маградзе, использовавший цитаты из стихотворений грузинских поэтов-классиков — Акакия Церетели, Григола Орбелиани и Галактиона Табидзе. Текст Грузинский текст Русский перевод Моя икона — родина, Иконостас — весь мир, Освещённые горы, долины, Брошенные жребием у Бога. Свобода сегодня наша Будущему поёт славу, Утренняя звезда поднимается И меж двух морей воссияет, Слава свободе, Свободе слава! Абхазский текст Ашәa aзaҳҳәоит ҳныхa, ҳaҧсaдгьыл Иҳaзгәaкьоу, иҧшьоу ҳтәылa. Мрaлa ирлaшоуп ҳa ҳaдгьыл, Уи aзоуп изaхьӡу aмрaтәылa. Иaхьa иҳaмоу aхaқәиҭрa Ашәa aзaҳҳәоит гәырӷьa бжьылa Аеҵәa ҩ-мшынк рыбжьaрa Икaҧхоит Анцәa имч aлa. Иныҳәaзaaит aхaқәиҭрa, Ахaқәиҭрa aмч-aлшa! Осетинский текст Мӕ дзуарыныв - фыдыбӕстӕ, Дзыуӕртынывтӕ ӕнӕхъхъӕн дуне, Арфӕгонд хӕхтӕ, фӕзтӕ. Нысан ӕппӕрст Хуыцауы разы. Сӕрибардзинад абон мах у, Фидӕнмӕ зары Табу, Сӕумӕйы ӕстъалы, ӕсхизы Амӕ дыууа денджызы ӕхсӕн ӕссырдтивы, Табу сӕрибардзинадӕн Сӕрибардзинадӕн табу! См. также Славься, небесный благословитель — гимн Грузии в 1918—1921 и в 1990—2004 годах Примечания Ссылки Музыка гимна (без слов) Грузия Государственные символы Грузии Песни 2004 года Песни по алфавиту Песни Грузии Песни на грузинском языке Произведения Захария Палиашвили


Множество всех подмножеств (булеан, показательное множество) — множество, состоящее из всех подмножеств данного множества (включая пустое множество и само множество ); обозначается или (так как оно соответствует множеству отображений из в ). Если два множества равномощны, то равномощны и соответствующие множества всех подмножеств. Обратное утверждение (то есть инъективность операции для кардиналов) является независимым от ZFC. В категории множеств можно снабдить функцию структурой ковариантного или контравариантного функтора следующим образом: ковариантный функтор отображает функцию в функцию такую, что она отображает в образ относительно ; контравариантный функтор отображает функцию в такую, что она отображает в полный прообраз относительно . Мощность конечного множества подмножеств Справедливо следующее утверждение: число подмножеств конечного множества, состоящего из элементов, равно . Результат доказывается методом математической индукции. В базе, у пустого множества () только одно подмножество — оно само, и . На шаге индукции утверждение считается установленным для множеств мощности и рассматривается произвольное множество с кардинальным числом ; зафиксировав некоторый элемент , подмножества множества разделяются на два семейства: , содержащие , , не содержащие , то есть являющиеся подмножествами множества . Подмножеств второго типа по предположению индукции , подмножеств первого типа ровно столько же, так как подмножество такого типа получается из некоторого и притом единственного подмножества второго типа добавлением элемента и, следовательно: и . По индукционному предположению и , то есть: . См. также Аксиома множества подмножеств Теорема Кантора Континуум-гипотеза Примечания Литература Операции над множествами Кардинальные операции (теория множеств)


Хаза́рский кагана́т, Хаза́рия (650—969) — средневековое государство, созданное тюркским кочевым народом — хазарами. Выделился из Западно-Тюркского каганата. Контролировал территорию Предкавказья, Нижнего и Среднего Поволжья, современного Северо-Западного Казахстана, Приазовье, восточную часть Крыма, а также степи и лесостепи Восточной Европы вплоть до Днепра. Центр государства первоначально находился в приморской части современного Дагестана, позже переместился в низовья Волги. Часть правящей элиты приняла иудаизм. Долгое время Хазария соперничала с Арабским халифатом в борьбе за господство в Закавказском регионе. В политической зависимости от хазар находился ряд восточнославянских племенных союзов. История Ранняя история. VI век Первоначально хазары представляли собой одно из многочисленных кочевых племён, перемещавшихся из Азии в ходе Великого переселения народов. Они говорили на одном из ранних тюркских языков и, как можно судить по косвенным данным, по-видимому, принадлежали к племенам огурской группы, первые из которых появились в Европе в 463 году. Наиболее ранним достоверным известием о хазарах считается упоминание в списке народов, перечисленных Псевдо-Захарием в 555 году. В качестве их европейской родины в источниках фигурирует область Берсилия, локализуемая в равнинной части современного Дагестана. В первой половине VI века хазары находились под влиянием объединения савиров, в составе их войск совершали успешные набеги на Закавказье. Владевший регионом Сасанидский Иран с трудом отражал этот натиск. При шахе Хосрове Ануширване (531—579) персы построили знаменитые Дербентские укрепления, которые перекрыли узкий проход между Каспийским морем и Кавказскими горами, но всё же не стали панацеей от нашествий кочевников. Традиция приписывает Хосрову строительство будущих хазарских городов в Дагестане — Беленджера и Семендера. Оба пункта первоначально являлись центрами одноимённых племён. К Семендеру, возможно, имеет отношение племя забендер, родственное аварам, которые, двигаясь вслед за савирами, прошли через Кавказ в 550-е годы. В 562 году савиры были разгромлены Ираном и вместе с частью хазар были переселены в Закавказье. Осколок савирского союза продолжал существовать в Дагестане, где был известен под именем «гуннов». Возвышение хазар связано с историей Тюркского каганата, с владыками которого хазарские правители, вероятно, состояли в родственных отношениях. Алтайские тюрки, возглавляемые каганами из рода Ашина, создали в 551 году огромную империю, которая вскоре разделилась на восточную и западную части. Во 2-й пол. VI века орбита Западно-Тюркского каганата достигла каспийско-причерноморских степей, и все местные объединения признали его главенство. Экспансия в Закавказье и Причерноморье. VII век Как значительная военная сила хазары впервые упоминаются в связи с ирано-византийской войной 602—628 гг., в которой хазарский правитель Джебукаган стал главным проводником тюркско-византийского союза, направленного против Ирана. В 627 году хазарское войско разграбило Кавказскую Албанию и, соединившись с византийцами, взяло штурмом Тбилиси. Начиная с 630 года многочисленные междоусобные столкновения привели к развалу Западно-Тюркского каганата. Результатом этого стало появление на его периферии в степях Восточной Европы двух новых политических образований. В Причерноморье возникла Великая Болгария, основанная ханом Кубратом в 632 году, а в Прикаспийском регионе — Хазария. Хазары первое время себя никак не проявляли, тогда как Болгарское объединение стало мощной политической силой, но этот расцвет оказался кратковременным. После смерти Кубрата булгарская орда раздробилась между его сыновьями. Хазары воспользовались этим, и в результате столкновения в 660-х гг. часть булгар, возглавляемая ханом Аспарухом, откочевала за Дунай, положив начало современной Болгарии, а оставшаяся часть признала власть хазар. По-видимому, после этого события правитель Хазарии принял высший в кочевой иерархии титул кагана. К концу VII века хазары контролировали бо́льшую часть степного Крыма, Приазовья и Северного Кавказа. Неясно, как далеко простирался их контроль над степями к востоку от Волги (история этого региона менее всего освещена в письменных источниках). Однако бесспорно, что историческим последствием хазарской гегемонии стала остановка непрерывного потока кочевников, следовавших из Азии в Европу, что имело позитивные последствия для восточнославянских племён и народов Центральной Европы. В этот период внимание Хазарии было обращено на Закавказье, чьи земледельческие государства сулили кочевникам богатые источники добычи. Вторжения туда осуществлялись двумя путями: через Дербент — в Кавказскую Албанию, Армению и далее в Иран или, реже, через Дарьяльское ущелье, расположенное на территории алан и ведущее в Грузию. Влияние хазар в регионе было столь значительным, что в ряде восточных языков Каспийское море получило название «Хазарского». Однако экспансия хазар натолкнулась здесь на встречный натиск, когда на месте Сасанидского Ирана возник Арабский халифат. Его войска оккупировали Грузию и Кавказскую Албанию, после чего в 653 году вышли за Дербент и атаковали хазарское владение Беленджер. Столкновение закончилось разгромом арабского войска и гибелью его предводителя Салмана ибн Раби. Из-за внутренних смут в последующие десятилетия Халифат утратил контроль над регионом. Хазары в это время взимали дань с Кавказской Албании и совершили ряд набегов, из которых самый крупный состоялся в 685 году. В сражении с ними погибли правители Грузии, Армении и Албании, а также один из арабских эмиров, разбитый поблизости от Мосула. Войны с арабами. VIII век С установлением в Халифате династии Омейядов арабские завоевания возобновились одновременно в нескольких направлениях: против вестготов на западе, тюрок на востоке и византийцев и хазар на севере. На этот раз арабы прочно закрепились в Закавказье, и в начале VIII века развернулась непрерывная череда арабо-хазарских войн, успех в которых сопутствовал попеременно как той, так и другой стороне. Временами противники совершали глубокие рейды на вражескую территорию. Хазария действовала в союзе с Византией, которая оборонялась от Халифата в Малой Азии. Когда в 717—718 гг. арабы осадили Константинополь, хазары оттянули на себя часть их сил, вторгнувшись в Кавказскую Албанию и Азербайджан. В конце 730 года состоялся самый масштабный набег хазар. Им руководил сын кагана — Барджиль. Нападению подвергся иранский город Ардебиль. 25-тысячное арабское войско было разбито, погиб один из высокопоставленных военачальников Халифата — Джаррах. Отдельные хазарские отряды дошли до Диярбакыра и окрестностей Мосула. Но уже к началу следующего года свежее арабское войско под командованием Саида ал-Хараши, которого затем сменил Маслама (именно он десятилетием ранее осаждал столицу Византии), выбило хазар со всех захваченных позиций, и бои переместились на территорию каганата. Война продолжилась в 732/733 году, хазарский каган был ранен в сражении поблизости от Дербента. Контроль над стратегической крепостью окончательно перешёл к арабам. В 737 году арабский полководец Марван ибн Мухаммад (будущий халиф) во главе 150-тысячной армии внезапно вторгся в Хазарию одновременно через Дербент и Дарьял. Войска взяли штурмом хазарскую столицу Семендер и достигли города ал-Байда, в котором располагалась ставка кагана. Каган бежал вглубь своих владений. В погоне за ним арабы зашли на север дальше, чем когда-либо: вплоть до «Славянской реки» — по-видимому, Дона или Волги. Хазарская армия была разбита, и каган запросил мира. В обмен на сохранение трона он пообещал принять ислам, но эта процедура, по-видимому, была номинальной. Хазария сохранила независимость, а арабы ушли с Северного Кавказа. Вскоре в Халифате вновь возникла смута. К власти там пришла династия Аббасидов, которая отказалась от дальнейшей экспансии на север. Таким образом, Хазарский каганат заслонил собой от арабской экспансии Восточную Европу и помог выстоять Византии. Во 2-й пол. VIII века после двадцатипятилетнего перерыва хазары предприняли ещё два набега на Закавказье: в 762—764 и 799 годах. В 780-е гг. они оказали помощь абхазскому правителю Леону II, провозгласившему независимость от Византии. После чего их вмешательство в дела региона прекратилось. Геополитическим последствием арабского натиска стало перемещение населения Хазарии от опасного кавказского пограничья во внутренние районы — Подонье, где расселились аланские племена, и Поволжье. В низовьях Волги возникла новая хазарская столица — Итиль, вскоре превратившаяся в крупный торговый центр. Дагестан со старой столицей Семендером из центральной области превратился в южную окраину Хазарии. Вероятно, в русле этих же процессов произошло появление булгар и савир (сувар) в Среднем Поволжье и Прикамье, где в IX веке возникла Волжская Булгария. С переориентацией внимания на север нередко связывают установление хазарской гегемонии над восточными славянами, хотя сведений о точной дате этого события нет. Отношения с Византией. VIII век Соседство с византийскими владениями на Крымском полуострове приводило к участию хазар в политике Империи. Около 704 года к кагану Ибузиру Глявану обратился за помощью свергнутый император Юстиниан II, находившийся в ссылке в Херсонесе. Каган дал ему в жёны свою сестру и пообещал помощь, но затем под влиянием действующего императора изменил своё решение и приказал убить. Юстиниан сумел бежать к дунайским булгарам и с их помощью вернулся к власти. Первое время его отношения с хазарами оставались дружественными, и каган посетил Константинополь, где был с почётом принят. От хазарской жены, в крещении получившей имя Феодора, у Юстиниана родился сын, сразу же объявленный соправителем. Опасаясь гнева Юстиниана, жители Херсонеса добровольно перешли под покровительство хазар, и в городе при сохранении самоуправления появился хазарский наместник — тудун. Опасения горожан подтвердились: в 710 году Юстиниан захватил Херсонес, казнил местную знать, а тудуна пленил и отослал в Константинополь.