Skip to content

Jardinesdelareina/learn_c

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

94 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Язык программирования C

 

Данный репозиторий является конспектом самых разных источников:

Лекции Сергея Балакирева по языку C

Курс по языку C для первого курса МФТИ Татьяны Дербышевой и Татьяны Овсянниковой

CS50 (Гарвардский курс по основам программирования)

Установка в Windows

Компилятор gcc (GNU Compiler Collection)

Программа-установщик компилятора minGW (Добавить в Path путь C:\MinGW\bin)

Установка в Linux

sudo apt update - обновление пакетов Linux;

sudo apt install cmake gcc clang gdb build-essential - установка:

  • cmake - инструмент для автоматизации процесса сборки программного обеспечения,
  • gcc - компилятор языка C,
  • clang - альтернативный компилятор C,
  • gdb - отладчик для программ,
  • build-essential - инструмент для автоматизации процесса сборки программного обеспечения;

sudo apt install valgrind - установка утилиты для отладки и обнаружения утечек памяти; valgrind --leack-check=full ./main - запуск проверки программы

Для запуска программы на C в PowerShell или bash ввести:

gcc -Wall -Wextra main.c

.\a

Чтобы задать свое имя исполняемому файлу:

gcc main.c -o main -Wall -Wextra -std=c99 -pedantic

  • -Wall включает все стандартные предупреждения компилятора (предупреждения о неиспользуемых переменных, некорректных вызовах функций и тд.)
  • -Wextra включает дополнительные предупреждения (предупреждения о неиспользуемых аргументах функций, несоответствие типов указателей и тд.)
  • -std=c99 указывает стандарт языка C
  • -pedantic активирует проверку на соответствие стандарту языка C
Расширения для VS Code:
  • C/C++
  • Code Runner (после установки программа компилируется нажатием CTRL + Alt + N)

В .vscode/tasks.json в список args добавить "-std=c99", после этого программа запускается CTRL + Shift + B

CS50

Стандартная библиотека языка C

Типы данных

Тип данных 16 бит 32 бит 64 бит Описание Диапазон
char 1 1 1 Символьный [0; 255] или [-128; 127]
short[int] 2 2 2 Целочисленный [-32768; 32767]
int 2 4 4 Целочисленный [-32768; 32767] или [-2147483648; 2147483648]
long[int] 4 4 8 Целочисленный [-2147483648; 2147483648]
long long[int] 8 8 8 Целочисленный ...
float 4 4 4 Вещественный ...
double 8 8 8 Вещественный ...
long double 10 10 10 Вещественный ...
Модификаторы (только для целочисленных типов):
  • unsigned - беззнаковый диапазон
  • signed - знаковый диапазон

short, int, long, long long по-умолчанию signed

Спецификаторы преобразований ввода/вывода

Спецификатор Описание
%d Целое число со знаком в десятичной форме (приводится к int)
%i Целое число в десятичной, 8ной или 16ной системах (приводится к int)
%u Целое unsigned число в десятичной форме (приводится к unsigned int)
%o Целое число в 8ной форме (приводится к int)
%x, %X Целое число в 16ной форме (приводится к int)
%f, %e, %g, %F, %E, %G Вещественное число (приводится к float)
%c Символ в соответствии с текущей кодовой таблицей (приводится к char)
%s Строка, читается до первого пробела, перевода строки или табуляции
h %hd, %hi - для short int, %hx, %ho, hu - для unsigned short
hh %hhd - для signed char, %hhu - для unsigned char
l %ld, %li - для long int, %lf, %lg, %le - для double
L %Lf, %Lg, %Le - для long double
ll (в стандарте C99) %lld - для long long int, %llu - для unsigned long long
Цифры Максимальная ширина ввода
* Пропуск данных
Функция printf()
int num;
printf("Num: %d\n", num);
Функция scanf()
int x;
int input = scanf("%d", &x);
printf("input = %d, value = %d\n", input, x);

В переменную input будет помещено количество принятых функцией scanf() значений. В примере - 1. С помощью &x происходит помещение введенных данных в переменную x.

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

Операция Обозначение Приоритет (чем выше значение, тем приоритетнее операция)
ИЛИ || 1
И && 2
НЕ ! 3

Директива #include

#include <stdio.h> сначала происходит поиск в системных каталогах, затем в рабочем

#include "utils.h" сначала происходит поиск в рабочем каталоге, затем в системных

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

Директивы условной компиляции

Директива Описание
#if Проверка произвольного условия
#else Определение условия "иначе"
#endif Завершение блока условия
#ifdef Проверка на наличие макроимени в текущем модуле
#ifndef Проверка на отсутствие макроимени в текущем модуле
#elif Аналог else if, определение условия "иначе"
#elifdef Проверка на наличие макроимени в условном блоке "иначе"
#elifndef Проверка на отсутствие макроимени в условном блоке "иначе"

Цикл for

for (инициализация; условие; обновление) { // тело цикла // операции, которые нужно выполнить на каждой итерации }

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

  2. условие - выражение, которое проверяется перед каждой итерацией цикла. Если условие истинно, то тело цикла выполняется. Если условие ложно, то цикл прекращается и исполнение переходит к следующей инструкции после цикла.

  3. обновление - операция или изменение переменных, которые должны происходить на каждой итерации цикла. Этот блок выполняется после каждой итерации перед проверкой условия.

for(int value = 1000, value > 0, --value)
    printf("%d", value);

Цикл while

Цикл выполняется до тех пор, пока верно условие.

int num = 0;
    
while (1) {
    num += 1;
    printf("Number: %d\n", num);
}
do/while

Цикл с постусловием. Это означает, что условие проверяется после каждой итерации цикла. Таким образом, тело цикла выполняется хотя бы один раз, даже если условие изначально ложное.

do { // тело цикла } while (условие);

int i = 1;

do {
    printf("%d\n", i);
    i++;
} while (i <= 10);

switch/case

Синтаксис switch/case:

switch(symbol) {
    case 'a':
    case 'A':
        printf("Symbol A\n");
        break;
    case 'b':
    case 'B':
        printf("Symbol B\n");
        break;
    default:
        printf("Any symbol\n");
}

Указатели

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

char num = 100;
char *nm;           // объявление указателя для работы с типом char
nm = &num;          // взятие адреса переменной num и присваивание его указателю nm
char x = *nm;       // получение значения по адресу переменной nm
*nm = 200;          // запись значения в ячейку, где расположена переменная num

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

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

void increment(int *num) {
    (*num)++;
}

int main() {
    int num = 5;
    printf("Before: %d\n", num);
    increment(&num);
    printf("After: %d\n", num);
    return 0;
}

В этом примере передается указатель на переменную num в функцию increment, которая увеличивает значение переменной на 1. Затем значение переменной num изменяется после выполнения функции.

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

Значение указателя изменяется на размер типа данных, для которого он определен.

int num = 10;
int *ptr_f = &num;
printf("%u\n", ptr_f);
ptr_f += 5;
printf("%u\n", ptr_f);

Первый вывод: 898233836 Второй вывод: 898233856 Тип указателя int, int занимает 4 байта, 5 * 4 = 20. Значение адреса изменяется на 20.

Указатели как параметры функций
void get_pointers(int* one, int* two)
{
    int three = *one;
    *one = *two;
    *two = three;
}

Строки

Экранирование и спецсимволы

escape-последовательность Код ASCII Описание
\n 0x0A Перевод на новую строку
\r 0x0D Перенос каретки
\t 0x09 Табуляция
\' 0x27 Экранирование одинарной кавычки
\" 0x22 Экранирование двойной кавычки
\? 0x3F Экранирование знака вопроса
\\ 0x5C Экранирование обратного слэша
\0 0x00 Символ конца строки
\x<число> Символ с указанным шестнадцатиричным значением
\uxxxx Символ с кодом xxxx в UNICODE (в стандарте C99)

assert

assert выполняет выражение, если оно истинно, выполнение программы происходит без изменений. Если выражение ложно, то выполнение программы останавливается и выполняется диагностика.

size_t

size_t является беззнаковым целочисленным типом данных, используемым для представления размеров объектов в памяти. Он выбирается таким образом, чтобы быть достаточно большим, чтобы вместить размер любого объекта в памяти. Обычно size_t имеет размер, достаточный для представления максимального возможного размера массива или объекта данных, который может быть выделен в памяти.

size_t широко используется вместе с операторами sizeof и в функциях, которые выполняют операции на памяти, таких как malloc, memcpy, strlen и другие, чтобы представить и возвращать размеры объектов в памяти.

static и extern

Ключевые слова static и extern относятся к спецификаторам доступа переменных и функций.

static:

  • Если static используется с переменной внутри функции, то эта переменная становится локальной статической. Она сохраняет свое значение между вызовами функции и инициализируется только один раз.
  • Если static используется с глобальной переменной или функцией, они становятся доступными только в текущем файле (имеют внутреннюю видимость). Такие переменные и функции не могут быть использованы или видимы из других файлов.

extern:

  • Используется для объявления переменной или функции, которая определена в другом файле.
  • Когда переменная или функция объявлена как extern, компилятор знает, что она будет определена в другом месте и можно использовать без ошибки "повторного определения".
  • Также используется для доступа к глобальным переменным или функциям, объявленным в других модулях.

enum

Ключевое слово enum используется для определения пользовательских наборов именованных констант, которые представляют собой список значений. Такое перечисление может использоваться для лучшей читаемости кода и упрощения работы с константами.

enum any_values
{
    one = 1,
    two = 2,
};

int main(void)
{
    enum any_values enum_values = val;
    switch(enum_values) {
        case one:
            puts("Value 1");
            break;
        case two:
            puts("Value 2");
            break;
    return 0;
    }
}

typedef

Ключевое слово typedef используется для создания псевдонима для существующего типа данных. Это может быть полезно для упрощения именования сложных типов данных или улучшения портативности кода.

typedef unsigned int uint32_t;

В этом примере создается псевдоним uint32_t для типа unsigned int. Теперь можно использовать uint32_t вместо unsigned int для объявления переменных или функций.

Использование псевдонимов с помощью typedef может сделать код более понятным и гибким.

Структуры

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

Пример объявления структуры в C:

struct person {
    char name[50];
    int age;
    float height;
}

Здесь объявляется структура person, которая содержит три поля: name типа char[50], age типа int и height типа float.

Чтобы создать переменную типа структуры, используется объявленное имя структуры, за которым следует имя переменной:

struct person person1;

Затем можно получить доступ к полям структуры с помощью оператора точки:

strcpy(person1.name, "John");
person1.age = 30;
person1.height = 180.5;

Также можно объявить структуру с помощью typedef, чтобы использовать созданный тип структуры, не указывая ключевое слово struct при объявлении переменных:

typedef struct {
    char name[50];
    int age;
    float height;
} PERSON;

Теперь можно создать переменные типа PERSON без использования struct:

PERSON person2;

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

Работа с файлами

Режим Описание
"r" Открытие текстового файла только на чтение.
"w" Открытие текстового файла только на запись. Если файл не существует, то он создается. Если существует, то все его прежнее содержимое удаляется.
"a" Открытие текстового файла на дозапись (новые данные добавляются в конец файла). Если файл не существует, то он создается.
"r+" Открытие текстового файла для чтения и записи одновременно.
"w+" Открытие текстового файла для чтения и записи. Если файл не существует, то он содается. Если существует, то все содержимое удаляется.
"a+" Открытие текстового файла для чтения и записи. Добавлять данные можно только после имеющегося содержимого. Читать можно все данные. Если файл не существует, то он создается.

Segmentation fault

Ошибка "Segmentation fault" (Segmentation fault (core dumped)) возникает, когда программа пытается обратиться к памяти, которая не была выделена ей или к которой у нее нет доступа. Это может происходить, например, при обращении к недопустимому указателю, при выходе за границы массива или при доступе к памяти, которая была освобождена.

Возможные причины ошибки Segmentation fault:

  1. Недопустимая работа с указателями: попытка работать с нулевым указателем или освободить память, которая уже была освобождена.
  2. Выход за границы массива: при обращении к элементу массива за его границами.
  3. Недопустимые операции с памятью: попытка чтения или записи в неправильный адрес памяти.
  4. Неправильное использование указателей: использование указателей, указывающих в неправильное место памяти.
  5. Неправильное использование функций: передача неправильных аргументов функциям или неправильное использование возвращаемых значений.

Для исправления ошибки Segmentation fault необходимо тщательно проверить код, убедиться, что указатели корректно инициализированы, не выходят за границы памяти и не используются после ее освобождения.

About

Learning C language

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published