Практика языка C (МФТИ, 2023-2024). Интермедия: командная строка, файлы и вариабельные аргументы.

  Рет қаралды 4,656

Konstantin Vladimirov

Konstantin Vladimirov

Күн бұрын

Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики.
На этом занятии мы поговорим о файлах и всём что естественно затронуть вокруг них, в частности про аргументы командной строки и про функции с вариабельным числом аргументов.
Семинарист: Константин Владимиров.
Дата: 17 ноября 2023 года.
Съёмка: Марк Гончаров.
Звук: Юлий Тарасов.
Предыдущий семинар: • Практика языка C (МФТИ...
Следующий семинар: • Практика языка C (МФТИ...
Слайды к занятиям: cs.mipt.ru/wp/?page_id=7775
Примеры кода: github.com/tilir/c-graduate
Задачник: olymp1.vdi.mipt.ru/
Timeline
00:00 Аргументы функции main
09:15 Поиск в файлах: первый шаг
12:40 Перевод строки в число
18:55 Работа с файлами
26:30 Просто открыть и закрыть
30:50 Права доступа
35:22 Форматный ввод и вывод
41:55 Поиск в файлах
45:15 Время решать задачи
46:50 Печать в строчку
50:30 Вариабельные аргументы
58:24 Написать printf и похожие функции
01:09:30 Разбор задач и завершение
Errata:
* Пока пусто

Пікірлер: 30
@DART2WADER
@DART2WADER 6 ай бұрын
Огонь, эти лекции зайдут "встройщикам".
@almatytelecom1
@almatytelecom1 3 ай бұрын
классные лекции
@McGewen
@McGewen 6 ай бұрын
ТОП!
@alex_s_ciframi
@alex_s_ciframi 5 ай бұрын
Константин, спасибо за лекцию. 42:35 - опечатка "лл" И, кстати, в одной из лекций был вопрос - почему полно народу в дискорде, но на стриме никто не сидит. Ссылки таки нужно выкладывать, стримы я, например, могу только позднее смотреть. Все ссылки я себе сохраняю :) Смотрю, как появляется возможн7ость - позже на месяц, на три :D
@xaoc3932
@xaoc3932 6 ай бұрын
Эх, не хватает времени на всё(, вот вроде и видос есть полезный , интересный, а уже минут через 15 спать надо((
@tilir
@tilir 6 ай бұрын
Как я вас понимаю....
@antonpetrenko9176
@antonpetrenko9176 4 ай бұрын
Благодарю за лекции, Константин! Весьма увлекательно и познавательно. 5:55 разве размер массива argv не argc+1?
@user-nt1re9ym4i
@user-nt1re9ym4i 6 ай бұрын
Спасибо за лекцию, очень нравится, что даже довольно скучные вещи у вас получается объяснять интересно и на реальных примерах, жалко правда, что в этой лекции всего 1 задача на подумать, но это понятно, т.к. базового материала довольно много. Касательно размера буфера в PrintFError, задача действительно не тривиальная, и вполне понятно, что вычисление точного размера будет эквивалентно по сложности написанию своей реализации функции принтф, однако достаточно ведь только примерно оценить этот размер, для чего необходимо будет только обработать флаги, подставить максимально возможный символьный размер для каждого спецификатора, кроме строк и добавить вычисленные размеры строк, ну и добавить длину строки формата. Хотя также выглядит весьма здравым решением отдать вычисление порядка буфера юзеру и просто принимать дополнительный аргумент. Также есть вопрос, насколько вообще эффективно использовать функции с префиксом v, когда в языке присутствует вариадик макрос? лично мне кажется, что неэффективно, т.к. передача va_list в аргумент уберает любую возможность оптимизации функций с переменным числом аргументов, в виде передачи некоторое количество этих аргументов через регистры, что реализуют многие компиляторы. Ну т.е. не лучше ли функции с простой логикой, как например PrintFError без вычисления размера буфера, выносить в макросы с переменным числом аргументов?
@user-qg7tv6hd2u
@user-qg7tv6hd2u 6 ай бұрын
Можете подсмотреть в соседнем C++ ostream и новый format - выполнение части в компайл-тайме, типобезопасность, и конечно же жирность да вагон нюансов. Если закручивать гайки в локальных алгоритмах общего назначения, выйдет подобно. А так, погоды это не сделает. Вычислять длину нужды нет, экономия наносекунд не ускорит затратные или алгоритмически неудачные части программы, в местах особо критичных к безопасности\производительности и подходы другие. Хотя сам потрошил исходники vsnprintf и пользуюсь своим форматированием) Приём с набором функций вроде addsfd(const char*, float, double); addii(int, int); вместо вариадиков и макросов для своего кода хорош, но это по ситуации и не про ускорение. Заодно убирает undefined behaviour, если дали промашку с типами при использовании вариадик-аргументов функции.
@tilir
@tilir 6 ай бұрын
Передача va_list конечно плоха для оптимизации. Но зачем нам оптимизирвоать случай когда у нас и так ошибка?
@user-qg7tv6hd2u
@user-qg7tv6hd2u 6 ай бұрын
Про printf аналоги. Выход однозначно лучше - vsnprintf и обработка возвращаемого значения. Или принимать буфер аргументом. Из "принято решать" есть ещё vasprintf, что конечно не советую никому. Также, в подобных функциях по очевидным причинам буфер обычно static и нередко общий для семейства функций, например в известном DearImGui. Важный нюанс - компилятор не будет проверять fmt-строку таких функций в отличие от стандартных, что крайне чревато, ошибки легки и повсеместны. В GCC и MinGW решение: __attribute__((format(printf, 1, 2))) в начале объявления функции, в документации описано подробно. Вообще использовать функции без N, не имея инвариантов и надеясь на лучшее - а потом условные "эксперты" опеннета именуют С "дыряшкой".
@tilir
@tilir 6 ай бұрын
Мне не очень нравится идея статического буфера из-за поломанной многопоточной безопасности.
@Stedmiel
@Stedmiel 6 ай бұрын
подушню немножко. 4:03 в стандарте "argc должен быть неотрицательным". нулем тоже может быть (а вдруг вашу программу кто-то через execv вызвал с нуликами?). и argv[0] тогда тоже должен быть нулевым указателем (:
@tilir
@tilir 6 ай бұрын
Формально да. В реальности студенты этого не узнают пока не пройдут POSIX где-то на втором курсе.
@kemalbidzhiev1948
@kemalbidzhiev1948 3 ай бұрын
Очень круто, Большое спасибо! У меня возник вопрос по вариадическим аргументам. Вот есть функция sum(len, a, b, c, ...). Зачем там указывать len ? Видимо чтобы в va_list указать откуда отталкиваться и начать считывать. Почему нельзя было написать sum(...) нельзя ли начать считывать с самого начала аргументов, а не отталкиваться от последнего в сигнатуре ?
@tilir
@tilir 3 ай бұрын
Увы такой синтаксис не предусмотрен. Хотя конечно было бы куда легче.
@user-uh2lf1hn8d
@user-uh2lf1hn8d 6 ай бұрын
А лекции по Си есть записи или планируются ?
@tilir
@tilir 6 ай бұрын
Нет, лекции читаю не я и они не записываются. Но вы можете ориентироваться на литературу если где-то не хватает пояснений от меня на семинарах.
@dmitriy3510
@dmitriy3510 6 ай бұрын
Для любителей конспирологии. Закладывался ли смысл в синий задний фон...
@tilir
@tilir 6 ай бұрын
Нет он случайно сгенерирован. А вот генератор который был для этого использован очень и очень интересен: vk.com/fracgen И это НЕ нейросети.
@dmitryivanov5647
@dmitryivanov5647 6 ай бұрын
Разъясните, как f(x, ...) раскладывает на стек параметры - как оно там под капотом устроено?
@lwind4884
@lwind4884 6 ай бұрын
Параметры кладутся на стек в обратном порядке, т.е. от последнего к первому.
@dmitryivanov5647
@dmitryivanov5647 6 ай бұрын
как компилятор определяет размер стек-фрейма для функций вида f(x, ...) Variadic arguments /* va_list*/, если число аргументов и их тип неизвестно, может быть очень большим? пока непонятненько...
@lwind4884
@lwind4884 6 ай бұрын
@@dmitryivanov5647Насколько я помню, это было в одном из видео в этом курсе. Если в кратко, то компилятор никак не определяет размер стека. Стек начинается с одного из старших адресов памяти и растёт в сторону кучи во время выполнения программы, т.е. в сторону уменьшения адреса. Если стек-фрейм встречается с кучей, то это переполнение стека.
@tilir
@tilir 6 ай бұрын
Мы поговорим про ABI в том числе про ABI для varargs в той части где у нас будет ассемблер. Что-то вроде 5.3 - 5.4 как пойдёт.
@MVZ1983
@MVZ1983 Ай бұрын
Интересно, а почему Константин Игоревич не объявляет счетчик цикла прямо в круглых скобках в объявлении цикла. См. стр. 19 на 27:25 По-моему, объяснение чтобы видеть все переменные функции здесь не работает, т.к. переменная i используется только внутри цикла
@MVZ1983
@MVZ1983 Ай бұрын
Я имею в виду так for(int i=2;
@tilir
@tilir Ай бұрын
Когда я пишу на C++ я определяю все переменные насколько возможно близко к использованию. Когда я пишу на C я определяю всё в начале функции. Очень просто запомнить. Конкретно это полезно делать чтобы сразу видеть размер фрейма (с точностью до коалесинга).
@MVZ1983
@MVZ1983 Ай бұрын
@@tilir Спасибо за ответ и за классные ролики. То есть это привычка от работы на низком уровне...
@user-nz1wu2gg3n
@user-nz1wu2gg3n 6 ай бұрын
Лушие курсы по С
Её Старший Брат Настоящий Джентельмен ❤️
00:18
Глеб Рандалайнен
Рет қаралды 8 МЛН
When someone reclines their seat ✈️
00:21
Adam W
Рет қаралды 29 МЛН
Они убрались очень быстро!
00:40
Аришнев
Рет қаралды 3,3 МЛН
Алгоритмы на Python 3. Лекция №4
1:14:14
Тимофей Хирьянов
Рет қаралды 557 М.