Skip to content

yhaskell/readme-c

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

Шпаргалка по языку Си

Типы

Типы целых чисел

  • Размером (минимум) 1 байт: char, unsigned char, signed char
  • Размером 2 байта: short, short int, unsigned short, unsigned short int
  • Размером 4 байта: int, unsigned, signed, unsigned int, signed int, long, long int, unsigned long
  • Размером 8 байт: long long, unsigned long long

Типы чисел с плавающей точкой

float, double, long double

Массивы

Для каждой переменной типа T существует тип T[] -- "массив элементов типа T", а так же тип T[N] -- массив элементов типа T длины N".

void

Тип void не является типом в общем виде. Невозможно описать переменную типа void (хотя можно описать переменную типа void*). В основном void используется для определения функций без возвращаемого значения.

Перечисления

Перечисления -- первый способ добавить свой собственный тип в язык Си. Это делается так:

enum имя_переисления { ИМЕНА_МЕТОК, ЧЕРЕЗ_ЗАПЯТУЮ }; // точка с запятой в конце

Пример такого перечисления:

enum color_t { RED, BLUE, WHITE, BLACK };	

После этого в нашем языке появляется новый тип color_t, и мы можем использовать этот тип для переенных.

Константы внутри перечислений можно задавать с указанным числовым обозначением (в памяти переменные перечислений хранятся так же, как переменные типа int). Это позволяет нам делать, к примеру, следующее:

enum side_t { 
	TOP = 1, 
	BOTTOM = 2, 
	LEFT = 4, 
	RIGHT = 8, 
	FRONT = 16, 
	BACK = 32 
};

side_t to_color = TOP | BACK;

Почему это работает? В качестве числовых представлений наших меток мы выбрали степени двоек. Поэтому при использовании операции побитового или | в одну переменную можно записывать одновременно наличие нескольких меток.

Структуры

Структуры -- это второй способ создавать собственные типы данных в языке Си. Это делается так:

struct имя_структуры {
	тип_1 пер_1;
	тип_2 пер_2;
	...
	тип_n пер_n;
};

Таким образом, внутри структуры мы просто объявляем набор переменных.

Пример

struct point_t {
	double x;
	double y;
};

После этого мы можем создавать переменные типа point_t в нашей программе. Переменные-члены будут доступны для переменных структурных типов через точечную нотацию:

point_t zero;
zero.x = zero.y = 0.0;

double distance(point_t p1, point_t p2) {
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

Указатели

Указатель -- это специальная переменная, хранящая типизированный адрес в памяти.

Если T -- это тип, то T* описывает тип "указатель на область памяти типа T". C указателями можно произвести два действия:

Разыменование

Разыменование указателя -- это получение значения по адресу, записанному в указатель.

Например, если x -- это переменная типа int*, то *x будет являться значением типа int. Это значение является "левым": его можно использовать как в выражениях, так и как переменную слева от знака присваивания:

*p = 42;

Адресная арифметика

К каждому указателю можно прибавить или вычесть произвольное (целое) число. Эта операция масштабируется относительно типа указателя. Например, если p -- это указатель типа T*, то запись p+x (где x -- число) будет обозначать адрес в памяти, равный p + sizeof(T) * x. Так, к примеру, если p -- это указатель типа int*, то разница между ячейками p и p+1 будет составлять на большинстве машин 4.

Получение адреса переменной

Адрес произвольной переменной типа T можно получить с помощью оператора &. Его можно записать в переменную типа T*:

int x = 42;
int* p2x = &x;

Синтаксис

Программа на языке си записывается в файлы. В большинстве случаев эти файлы имеют раcширение .c. На верхнем уровне программа состоит из директив препроцессора, объявлений новых типов и глобальных переменных, а так же деклараций функций.

Выражение (expression)

В программировании выражение -- это комбинация слов языка, которая может быть интерпретирована согласно правилам языка Си как значение.

Примером выражения может являться:

  • Константа
  • Переменная
  • Вызов функций
  • Присваивание
  • Арифметическое или логическое выражение (операндами могут являться другие выражения).

Утверждение (statement)

Утверждение -- это минимальная конструкция языка, которую можно воспринимать как действие.

Утверждение-выражение

Утверждение-выражение (expression statement) -- это выражение, после которого идёт точкой с запятой. Несмотря на то, что каждое выражение можно превратить в утверждение, обычно это делают с утверждениями, обладающими побочными эффектами -- такими, как присваивания и вызовы функций.

Пример
7;							// вполне корректное, хотя и абсолютно бесполезное УВ
puts("Hello, world!");		// вызов функции
foo = getchar();			// присваивание

Объявление переменных

В языке Си переменные можно объявлять в любом месте программы. Синтаксис объявления переменных таков:

тип имя [= начальное_значение][, имя [= начальное значение]]*

(здесь выражения внутри квадратных скобках являются необязательными, а * обозначает, что этот кусок можно повторить много раз

Пример
int x;						// просто объявление переменной
int y = 42, z;				// переменная y объявлена с начальным значением, а z -- без

char z = getchar(), 
     w = getchar();			// z и w могут иметь разное значение

Блочное утверждение (block statement)

Блочное утверждение -- это набор утверждений, взятых в фигурные скобки.

{
   foo = bar();
   int x = 42;
}

Условие (if statement)

Условие -- одна из самых основных конструкций, позволяющая выбрать путь выполнения программы. Её синтаксис такой:

if (cond_expr) true_stmt [else false_stmt]

При выполнении кода условного утверждения сначала вычисляется cond_expr. Если его значение не является нулевым, то выполняется true_stmt. Иначе, если есть, выполняется false_stmt.

Примеры
if (x > 5) 							// простое условное утверждение
	puts("x is greater than 5");
else 
	puts("x is equal or less than 5");		

if (z < 0) z = -z;					// условие без блока else

if (x + y < z) {					// условие, в результате которого делается много действий
	int temp = x;
	x = z - y;
	y = z - temp;
}


if (x > 0)							// условное выражение может быть частью false_stmt
	puts("x is positive");
else if (x < 0) 
	puts("x is negative");
else 
	puts("x is null");

Циклы while и do while

Циклы while и do while повторяют действие, пока условие верно. Его синтаксис такой:

while (cond_expr) true_stmt
do true_stmt while (cond_expr);

При выполнении цикла while вычисляется cond_expr. Если это 0, то выполнение цикла завершается. В противном случае выполняется true_stmt, и выполнение переходит в начало.

При выполнении цикла do while сначала выполняется true_stmt, а потом вычисляется cond_expr. Если это 0, то выполнение цикла завершается в начало. Иначе выполнение переходит в начало.

Циклы while и do while так же называют "цикл с предусловием" и "цикл с пост-условием".

int x = 42;
while (x > 0)			// цикл с пред-условием
	printf("%d", x--);

do {					// цикл с пост-условием
	printf("%d", x);
} while (x > 0);

Цикл for

Цикл for -- это цикл с пред-условием с дополнительными действиями. Его синтаксис такой:

for (init_expr; cond_expr; iter_expr) true_stmt

При выполнении цикла for сначала выполняется утверждение-выражение init_expr;. Далее, пока cond_expr не 0, выполняется сначала true_stmt, а потом iter_expr;.

Пример
for (int i = 0; i < 42; i++) sum += i;

В цикле for все три выражения опциональны. Поэтому все следующие примеры корректны.

for (;;) ;						// бесконечный цикл, который ничего не делает.
								// то же, что и while (1);
					
for (int x = 0;x < 5; x++) ; 	// тело цикла не указано. Выполняется только iter_expr

for (; x > 5 ;) x--;			// в чистом виде while
Выход из тела цикла

Иногда возникает необходимость перестать выполнять тело цикла, и либо снова перейти к условию, либо вообще покинуть цикл. Утверждения continue; и break; соответственно делают именно это.

continue и цикл for

Следует помнить, что при использовании continue; iter_expr; выполняется.

Утверждение выбора switch

Switch позволяет выбрать действие в зависимости от значения выражения. Его синтаксис такой:

switch (expr) {
	case v1:
		[v1_stmt]*
	case v2:
		[v2_stmt]*
	/// ...
	default:
		[default_stmt]*
}

При выполнении утверждения switch сначала вычисляется значение expr. Далее выбирается метка case, соответствующая значению выражения. (Если такой нету, выбирается default. Если и метки default нету, то происходит переход к следующему за switch утверждению.)

После того, как метка выбрана, начинается последовательное выполнение всех утверждений, идущих за этой меткой (т.е. новая метка не прерывает выполнение switch). Если такое поведение нежелательно, то последним утверждением перед следующей меткой нужно поставить break;.

Пример
switch (x + y % 2) {
	case 0: 
		printf("Число %d чётное.\n", x + y);
		break;
	default: 
		printf("Число %d нечётное.\n", x + y);
}

switch (x % 10) {		// одно и то же действие по нескольким меткам
	case 2:
	case 3: 
	case 5: 
	case 7:
		printf("Остаток от деления %d на 10 простой.\n", x);
}

Функции и процедуры

Функция в языках программирования -- это набор действий, параметризованный набором переменных-"аргументов".

Определить функцию очень просто. Синтаксис определения такой:

тип_возвращаемого_значения имя_функции(аргументы) {
	[stmt]*
}

Синтаксис аргументов:

[тип_аргумента аргумент[,тип_аргумента аргумент]*]

После определения функции её можно вызывать по имени, указав значения аргументов в скобках через запятую.

Пример

void foo() {					// функция без возвращаего значения и аргументов, выводящая FOOOOOO на экран
	printf("FOOOOOOOOOO\n");
}

void bar(int count) {			// функция bar(count) выводит строчку BAAAA....AAR (количество А определяется аргументом count)
	putchar('B');
	for (int i = 0; i < count; i++) putchar('A');
	puts("R");
}

void baz(int x, int y) {		// функция, выводящая результаты различных арифметических операций
	printf("%d + %d == %d\n", x, y, x + y);
	printf("%d - %d == %d\n", x, y, x - y);
	printf("%d * %d == %d\n", x, y, x * y);
	printf("%d / %d == %d\n", x, y, x / y);
	printf("%d %% %d == %d\n", x, y, x % y);
}

Возвращаемое значение

В математике функция -- это закон, который набору аргументов сопоставляет результат. Так как программирование изначально часто использовалось для различных математических подсчётов, то неудивительно, что эту часть в программировании тоже сделали возможной. Для возвращения значения используется утверждение return (return statement):

int sum(int x, int y) {		// функция sum(x, y) возвращает, как ни странно, x + y
	return x + y;
}

About

README c documents

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published