Skip to main content

C: общее

Исходный код из книги по C

P. J. Plauger’s The Standard C Library - желательная для прочтения.

Поиск нужного пакета: 

apt-cache search manpages | grep ^manpag

Установка пакетов 

sudo apt install manpages-ru manpages-ru-dev

Список доступных локалей 

locale -a

Установка локали для man страницы 

LANG=ru_RU.utf8 man 2 open

Компиляция 

cc test.c
cc -0 test test.c

Вариант через gcc 

gcc -Wall -Wextra -Werror -g program.c -o my_program

Добавить поиск в текущей директории (чтобы не писать ./) 

export PATH=$PATH:.

Базовое описание языка

1 // A first program in C.
2 #include <stdio.h>
3 
4 // function main begins program execution 
5 int main(void) {
6    printf("Welcome to C!\n");
7 }

# - директивы препроцессора.

*.h заголовочные файлы, в которых содержится описание функций и ссылки на файлы с их расположением.

Переменные

Переменные можно просто объявлять и дополнительно инициализировать начальное значение. Размеры типов зависят от платформы и компилятора! Вывод размера:

sizeof(имя_типа);

Квалификаторы типов (модификаторы)

Они не создают новые типы, но изменяют их свойства.
const    Значение нельзя изменить    const int x = 5;
volatile    Значение может измениться внешне (прерывания, hardware)    volatile int status;
restrict    Указатель — единственный способ доступа к данным (для оптимизации)    int *restrict ptr;
signed    Тип со знаком (по умолчанию для char не определено)    signed char c;
unsigned    Тип без знака (только положительные числа)    unsigned int u;

Псевдонимы типов (typedef)

Позволяет дать новое имя существующему типу. 

typedef int my_int;           // my_int — это псевдоним для int
typedef unsigned long ulong;  // ulong — псевдоним для unsigned long

my_int x = 10;                // То же, что int x = 10;
ulong y = 100;                // То же, что unsigned long y = 100;

Часто используется для упрощения сложных типов: 

typedef struct {
    char name[50];
    int age;
} Person;                    // Теперь можно писать Person p; вместо struct Person p;

Базовые типы:

voidНет значений    Означает "отсутствие типа"Нет размера
integer (int)Целые числа, -2,147,483,648 … 2,147,483,6474
int var;
int var=7;

unsigned intБеззнаковое целое 0 … 4,294,967,2954
shortЧисла со знаком -32,768 … 32,7672
unsigned shortБеззнаковое короткое целое 0 … 65,5352
long
4 или 8    Зависит от платформы
unsigned long


long longОчень длинное целое8 байт
unsigned long long
8
floatДробные с точностью до 7 знака4
float var_float = 12.45;

doubleДробные с точностью 15 знаков8
long double
10, 12 или 16   Зависит от платформы
boolЛогическое
bool vr = true;

charСимвол1
char n = 'g';

unsigned charБеззнаковый символ 0 … 2551

Массивы

Хранят несколько элементов одного типа подряд в памяти. Из базовых. 

int numbers[10];           // Массив из 10 целых чисел
char name[50];             // Массив из 50 символов
double matrix[3][3];       // Двумерный массив (матрица 3x3)

Указатели (pointer)

Хранят адрес в памяти, где находится значение. 

int *ptr;                  // Указатель на int
char *str;                 // Указатель на char (строка)
void *generic;             // Универсальный указатель (на любой тип)

Перечисления (enum)

Определяют набор именованных целочисленных констант. 

enum Color {
    RED,    // 0
    GREEN,  // 1
    BLUE    // 2
};

enum Color favorite = GREEN;

Структуры Объединяют разные типы в один. 

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

struct Person person1;

Объединения (union)

Как структура, но все поля используют одну и ту же область памяти (экономят память).

union Data {
    int i;
    float f;
    char str[20];
};

union Data data;           // data.i, data.f, data.str занимают одну память

Преобразование типов.

Бывают явные (делает программист) и неявные (компилятор). Неявные делятся на:

  1. При присваивании результата вычисления переменной, тип результата к преобразуется к типу переменной. Округление происходит не по математическим законам, а путем отбрасывания значения.
  2. При  вычислении выражения операнды каждой операции преобразуются к какому-то одному типу (если они различаются), при этом результат операции будет того же типа. Правило «меньший» тип к «большему», для минимизации потерю информации. Операции преобразования сначала выполняются от самого глубокого до внешнего, одного приоритета слева направо.
float c = 5/6;

5 и 6 - целочисленные, поэтому результат целочисленный. И равен 0. Только после этого он преобразуется в float, но уже поздно. В с будет 0. А если сделать один операнд с плавающей точкой - второй преобразуется во float и дробная часть не потеряется. 

float c = 5.0/6;

Пример приоретизации операций: 

2 / 4 * 3,14 
// результат 0, так как одноуровневые операции слева направо

Явное преобразование: 

double result = (double)a / b;

 

 

Константы

добавляется слово const

const int var=7;

Комментарии

// comments
/* comments
long */

Циклы

 

for (j=0; j<9; j++) {}

 

Функции

Шаблон описания 

тип_возвращаемого_значения название(входящие аргументы) {

}

int add(int a, int b);     // Функция, возвращающая int
void print_message();      // Функция, не возвращающая значение
int (*func_ptr)(int, int); // Указатель на функцию

void - отсутствие аргумента

Функция int main(void) - точка входа.