Тёмный

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

Konstantin Vladimirov
Подписаться 20 тыс.
Просмотров 4,9 тыс.
50% 1

Практические занятия по языку 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:
* Пока пусто

Опубликовано:

 

13 июл 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

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