БДЗ ver 0306
.pdfБДЗ
Typical IVT
№1 скип
№1 скип
№2 при многократном подключении функции дублируются и компилятор не понимает что использовать
это фиксится #ifndef #define #endif
№3 флаг е - компиляция для остановки на стадии препроцессинга
№4 аналогично 2, 3
№5 -E — остановка после этапа препроцессирования - модифицированная программа
-S — остановка после этапа компиляции (создание ассемблерного кода) - ассемблерная программа -c — остановка после этапа ассемблирования (создание объектного файла) - машинный код
-o — ключ для задания имени выходного файла - целевой машинный код
№6 -lm — флаг для подключения математической библиотеки libm.so (link math)
№7 -Wall — включает большинство предупреждений компилятора -Wpedantic — требует строгого соответствия стандарту C -Werror — превращает все предупреждения в ошибки
№8 Форматирование файла (флаг -i означает "in-place" — изменения сразу в файле) clang-format -i main.c
Запуск статического анализа со всеми проверками clang-tidy main.c -checks=*
Запуск статического анализа с указанием стандарта языка clang-tidy main.c -- -std=c11ls
№9 -shared значит что библиотека динамическая
Wl передача напрямую линкеру, rpath,. вшивает путь, точка для рабочего каталога
№10 __GNUC__ for gcc
__clang__ for Clang
_MSC_VER for ms visual studio
для gcc:
__GNUC__ для основной версии __GNUC_MINOR__ дополнительно __GNUC_PATCHLEVEL__ для патчей
__i386__ х86
__x86_64__ 86 64 __arm__, __arm64__
№11 errno используется для файловых операций, управлений памятью, работы с потоками и процессами
№12 run: main
./main >> make run
№13 ez gg
№14 sudo apt-get update && sudo apt-get install build-essential
№15 Разделение на несколько CMakeLists.txt соответствует модульной структуре проекта Каждый модуль (библиотека, исполняемый файл) сам управляет своими исходниками, флагами компиляции, зависимостями.
Библиотека не обязана знать, как собирается приложение, которое её использует. Независимая сборка те Можно собирать только нужные цели: make mylib или make myapp, не трогая остальное.
ПЛИС Стр.1
PRIVATE
Нужно только самой цели для внутренней реализации. Потребители библиотеки об этом не знают.
PUBLIC
Нужно и самой библиотеке, и всем, кто её подключает.
Обычно это заголовочные файлы, которые включены в публичный API.
INTERFACE
Библиотеке самой не нужно, но обязательно для тех, кто её подключает. Характерно для header-only библиотек (только заголовки).
Что произойдет, если не указать target_include_directories для myapp?
Если библиотека лежит в кастомной папке (например, ../lib/), компилятор не найдёт заголовочный файл
№16 lelele
№17 ez gg
№18 какая то срань с памятью
№19 Строка кэша — это минимальный блок данных, которым процессор обменивается между оперативной памятью и кэшем.
Обычно её размер составляет 64 байта на современных процессорах x86-64. По строкам идти круче потому что в строку элементы попадают по порядку
№20 скип wsl2 не работает
№21 в дабл больше помещается
№22 ez gg
№23 число 0.1 не представимо точно в двоичной системе с плавающей точкой
№24 ez gg №25 ez gg
#26
void seconds_to_time(int n)
{
int hours = n/60/60;
int minutes = (n-hours*60*60)/60; printf("%d, %d", hours, minutes);
}
#27
const char* get_time_of_day(int n)
{
int hours = n/60/60;
int minutes = (n-hours*60*60)/60; if (hours>=0 && hours<=5){
return "night";
}
if (hours>=6 && hours<=11){ return "morning";} if (hours>=12 && hours<=17){return "day";}
if (hours>=18 && hours<=23){return "night";}
# 28
int middle_of_three(int a, int b, int c)
{
if (a>b && a<c || a<b && a>c) {return a;} else{
if (b>a && b<c || b<a && b>c) {return b;} else {return c;}
}
}
ПЛИС Стр.2
#29
int min_of_three(int a, int b, int c)
{
if (a<b && a<c){return a;}
else if (b<a && b<c) {return b;} else {return c;}
#30
void fizzbuzz(int n)
{
for (int i=1; i<(n+1); i++){
if (i%3==0 && i%5==0) {printf("%s \n", "fizzbuzz");} else if (i%3==0) {printf("%s \n","fizz");}
else if (i%5==0) {printf("%s \n","buzz");} else {printf("%d \n", i);}
}
#31
double my_function(int x)
{
return (x*x+5*x+6)/(1+x+x*x);
}
#32
int is_palindrome(const char *s)
{
int left = 0;
int right = strlen(s)-1;
while (left<=right){
if (s[left] != s[right]) {return 0;} left++;
right--;
}
return 1;
}
!!! Обычно из функций проверки возвращают 1/true, если условие выполнено (палиндром), и
0/false — если нет.
#33
#include <stdio.h>
double average(int n, int numbers[])
{
double sum = 0;
for (int i=0; i<n; i++){ sum+=numbers[i];} return sum/n;
}
int main(void)
{
int n; scanf("%d", &n); int numbers[100];
for (int i = 0; i < n; i++) scanf("%d", &numbers[i]);
printf("%.6f\n", average(n, numbers)); return 0;
}
#34
#include <stdio.h>
double progression(int a1, int d, int n)
{
ПЛИС Стр.3
for (int i=1;i<n;i++) {a1*=d;} return a1;
}
#35
#include <stdio.h> #include <stdlib.h>
int main(int argc, char *argv[])
{
int sum = 0;
if (argc<2){
printf("No numbers provided"); return 0;
}
for (int i=1; i<argc; i++) {sum+= atoi(argv[i]);}
printf("%d\n", sum); return 0;
}
1.argc (count) количество аргументов, argv (vector) массив строк, содержит сами аргументы
2.argc[1] - имя программы (argv[0] имя/путь к программе)
3.просто ноль выведет
4.аналогично
#36
#include <stdio.h> #include <math.h>
int solve_quadratic(double a, double b, double c, double *x1, double *x2)
{
double d = b*b-(4*c*a); if (d<0) {return 0;} else {
*x1 = (-b-sqrt(d))/2/a;
*x2 = (-b+sqrt(d))/2/a;
if (*x1 != *x2) {return 2;} else {return 1;}
}
}
int main(void)
{
double x1; double x2; double a, b, c;
scanf("%lf %lf %lf", &a, &b, &c);
int roots = solve_quadratic(a, b, c, &x1, &x2);
if (roots == 0)
printf("No real roots\n");
else if (roots==1) {printf("1 root: %f", x1);} else {printf("2 roots: %f, %f", x1, x2);} return 0;
}
КОМПИЛИРОВАТЬ ЧЕРЕЗ: gcc main.c -lm -o main, тк линковка иначе не подгружает математику
#37
#include <stdio.h>
unsigned long long factorial(int n)
{
ПЛИС Стр.4
if (n<0) {return -1;} unsigned long long fact = 1;
for (int i=1;i<n+1;i++) {fact*=i;} return fact;
}
int main(void)
{
int n; scanf("%d", &n);
double result = factorial(n); printf("%.0f\n", result); return 0;
}
#38 (?)
1.ast_func (с static inline) Компилятор встраивает тело функции непосредственно в точку вызова:
Нет инструкций call, экономится стабильно 4-6 строк инструкций за цикл
2.компилятор может выкинуть х если он не изменился после этапа цикла, удалить мертвый код, может сократить цикл до одного присваивания 3.их меньше становится
#39
#include <stdio.h>
int array_sum(int arr[], int n)
{
int sum=0;
for (int i=0;i<n;i++){sum+=arr[i];} return sum;
}
int main(void)
{
int n; scanf("%d", &n);
int arr[n];
for (int i=0;i<n;i++) {scanf("%d",&arr[i]);} printf("sum: %d", array_sum(arr,n));
return 0;
}
#40
#include <stdio.h>
int main(void)
{
int n; scanf("%d", &n);
int arr[n];
for (int i=0;i<n;i++) {scanf("%d",&arr[i]);}
int duplicates[n];
int found = 0;
for (int i=0;i<n;i++){ for (int j=i+1;j<n;j++){
if (arr[i]==arr[j]) { duplicates[found]=arr[i]; found+=1;
ПЛИС Стр.5
}
}
}
if (found==0) {printf("no duplicates");} for (int i=0;i<found;i++){
if (duplicates[i]!=duplicates[i+1]) {printf("duplicates: %d ",duplicates[i]);}
}
return 0;
}
#41
#include <stdio.h>
int main(void)
{
int n; scanf("%d", &n);
int arr[n];
for (int i=0;i<n;i++) {scanf("%d",&arr[i]);}
int max=arr[0]; int min=arr[0];
for (int i=0;i<n;i++){
if (max<arr[i]){max=arr[i];} if (min>arr[i]){min=arr[i];}
}
if (n==0) {printf("%d, %d",0, 0);}
else {printf("max and min are %d, %d",max, min);}
return 0;
}
#42
#include <stdio.h>
int main(void)
{
int n; scanf("%d",&n); int arr[n];
for (int i=0;i<n;i++) {scanf("%d",&arr[i]);}
int sum[n];
for (int i=0;i<n;i++){ sum[i]=0;
for (int j=0; j<i+1;j++){ sum[i]+=arr[j];
}
printf("%d ", sum[i]);
}
return 0;
}
#43
1.указатель — переменная, которая хранит адрес другой переменной в памяти
2.если указатель константный его нельзя изменить, но значение его переменной можно
3.int const *const_ptr = &value;
// *const_ptr = 50; // Почему не компилируется? |
это указатель на константу |
|
int other_var = 5; |
|
|
// ptr_const = &other_var; // Почему не компилируется? |
это константный |
|
указатель
ПЛИС Стр.6
#44
Компилятор автоматически умножает число n на размер типа sizeof(type) при ptr+1 3. Чем отличается p + 1 от ((char*)p) + 1? в единице измерения сдвига.
#45
Выражение a[b] по определению эквивалентно выражению (*((a) + (b))) Неявное преобразование (Array-to-pointer decay):
В подавляющем большинстве выражений (например, в x + 1, *(x), при передаче в функцию) имя массива неявно и мгновенно преобразуется в указатель на свой первый элемент. x[1] -> *(x + 1). 1[x] -> *(1 + x)
#46
#include <stdio.h>
void swap(int *ptr_1, int *ptr_2)
{
int swap_ptr = *ptr_1; *ptr_1 = *ptr_2; *ptr_2 = swap_ptr;
}
int main ()
{
int arr[5] = {1,2,3,4,5}; swap(&arr[0], &arr[4]);
for (int i=0; i<5; ++i){printf("%d", arr[i]);} return 0;
}
#48
#include <stdio.h>
void swap(int *ptr_1, int *ptr_2)
{
int swap_ptr = *ptr_1; *ptr_1 = *ptr_2; *ptr_2 = swap_ptr;
}
int main ()
{
int arr[5] = {1,2,3,4,5}; swap(&arr[0], &arr[4]);
for (int i=0; i<5; ++i){printf("%d", arr[i]);} return 0;
}
#49
#include <stdio.h> #include <stdlib.h>
double* rand_arr (int n)
{
double *arr = (double*)malloc(n*sizeof(double));
for (int i=0;i<n;i++) {arr[i] = (double)rand()/100000;} return arr;
}
void print_arr (double* arr, int n)
{
printf("my array:\n");
for (int i=0;i<n;i++){printf("%f \n", arr[i]);}
}
ПЛИС Стр.7
double max_elem (double* arr, int n)
{
double max = arr[0]; for (int i=0; i<n; i++)
{
if (max<=arr[i]){max = arr[i];}
}
return max;
}
int main()
{
int n;
printf("array size: "); scanf("%d", &n);
double *arr = rand_arr(n); print_arr(arr, n);
printf("max element: %f", max_elem(arr, n));
return 0;
}
#50 Динамический двумерный массив
include <stdlib.h> #include <stdio.h>
double* rand_arr (int n, int m)
{
double *arr = (double*)malloc(n*m*sizeof(double)); for (int i=0; i<n; i++){
for (int j=0; j<m; j++){arr[i+j] = (double)rand()/10000/666;}
}
return arr;
}
void print_arr (double* arr, int n, int m)
{
printf("my array:\n"); for (int i=0; i<n; i++){
for (int j=0; j<m; j++){printf("%f ",arr[i+j]);} printf("\n");
}
}
double max_elem (double* arr, int n, int m)
{
double max = arr[0];
for (int i=0; i<n; i++){
for (int j=0; j<m; j++){
{
if (max<=arr[i]){max = arr[i];}
}
}
return max;
}
}
int main()
{
int n; int m;
printf("array size: "); scanf("%d %d", &n, &m); double *arr = rand_arr(n, m);
ПЛИС Стр.8
print_arr(arr, n, m);
printf("max element: %f", max_elem(arr, n, m));
return 0;
}
#51 Функция increase_array
void increase_array_size(int **a, int n, int n_new) { int *q;
q = (int*) realloc(*a, n_new*sizeof(int));
if (*a==NULL) { /* проверка успешности увеличения памяти */ printf("Error increase array size");
}
else {
*a = q;
}
}
#52
============================================================================================
= потом
#53 Односвязный список
#include <stdio.h> #include <stdlib.h> #include "list.h"
// Создание нового узла
Node* create_node(int value) {
Node *new_node = (Node*)malloc(sizeof(Node));
if (new_node==NULL) {printf("error"); exit(EXIT_FAILURE);} new_node->data = value;
new_node->next = NULL; return new_node;
}
// Добавление в конец
void push_back(Node** head, int value) { Node* new_node = create_node(value);
if (*head==NULL){*head = new_node; return;} Node *curr = *head; while(curr->next!=NULL){curr=curr->next;} curr->next = new_node;
}
// Вставка по индексу (0 — в начало)
void insert_at(Node** head, int value, int index) { Node* new_node = create_node(value);
if (*head==NULL){*head = new_node; return;}
if (index==0){new_node->next = *head; *head = new_node; return;} Node *curr = *head;
for(int i=0; i<index-1; i++){curr=curr->next;}
if (curr==NULL){printf("out of range!"); free(new_node);return;}
new_node->next=curr->next; curr->next = new_node;
}
// Удаление по значению (первое вхождение) void delete_value(Node** head, int value) {
Node* curr = *head; Node* prev = NULL;
while (curr->data!=value){prev = curr; curr = curr->next;}
ПЛИС Стр.9
if (prev==NULL){*head=curr->next;} else{prev->next = curr->next;} free(curr);
}
// Поиск элемента
Node* find(Node* head, int value) { Node* curr = head;
while (curr->data!=value){curr = curr->next;} return curr;
}
// Вывод списка
void print_list(Node* head) { Node* curr = head;
while (curr != NULL){ printf("%d ", curr->data); curr = curr->next;
}
// free(curr);
}
// Освобождение памяти
void free_list(Node* head) { Node* curr = head;
Node* prev = NULL;
while (curr->next != NULL){ curr = curr->next; free(prev);
}
free(curr);
}
#54
#include <stdio.h> #include <stdlib.h> #include "list.h"
Node* create_node(int value) {
Node* new_node = (Node*)malloc(sizeof(Node)); if(new_node==NULL){printf("malloc error"); exit(EXIT_FAILURE);} new_node->data = value;
new_node->next = NULL; new_node->prev = NULL; return new_node;
}
void push_back(Node** head, int value) { Node* new_node = create_node(value);
if (*head==NULL){*head = new_node;return;}
Node *curr = *head; while(curr->next!=NULL){curr=curr->next;} curr->next=new_node;
new_node->prev = curr;
}
void insert_at(Node** head, int value, int index) { Node* new_node = create_node(value);
if (*head==NULL){*head = new_node;return;}
if (index==0){new_node->next = *head; (*head)->prev = new_node; *head=new_node; return;}
Node *curr = *head;
for (int i=0; i<index-1; i++) {curr = curr->next;} // if (curr==NULL){printf}
ПЛИС Стр.10
