Спасибо Вам огромное за ваш труд! Особенно за внимание к деталям каждой темы, которую Вы разбираете!!! Не останавливайтесь пожалуйста!!! ❤
@andrey_sautenko Жыл бұрын
отдельное спасибо за концовку, связанную с С++!
@andredru427811 ай бұрын
Спасибо. Все понятно.
@СаняСанин-ш6у Жыл бұрын
вообще огонь уроки!🤙
@РусланКарнеенко10 ай бұрын
Спасибо
@КириллЧе-я5ы10 ай бұрын
О, элипсис… например void f() { printf(“hello”); } принимает сколько угодно аргументов. И получаем уб
@lego6757 Жыл бұрын
А как в C++ передать в функцию произвольное число заранее определённых разных классов (но с некоторыми одноименными методами), например "init_interfaces(SPI1, UART2);" когда неизвестно в каком порядке они будут поданы или вовсе без них("init_interfaces();") ? У меня было такое задание на собеседовании, смог решить не все условия и теперь меня этот вопрос уже долго мучает
@selfedu_rus Жыл бұрын
Через массив указателей на один единый базовый класс у всех этих классов.
@MrLeyt11259 ай бұрын
Чет вообще неудобно. А можно так же как и с main, которая через батник вызывается? int main(int argc, char** argv) и перебирать параметры через argv[1], argv[2]...argv[argc] ?
@pewpewpew8613 Жыл бұрын
Привет, у меня вопрос по варидическим функциям. Насколько я понимаю у нас есть указатель на самое начало стек фрейма и есть указатель на первый вариадический аргумент. Разве этого не достаточно для того что бы нам прочесть все переданные аргументы без явной передачи их кол-ва. Мы ведь можем читать начиная от первого аргумента до того момента пока мы не упремся в начало стек фрейма, всё что нам надо это знать тип аргументов. Или я чего не то не так понимаю?
@selfedu_rus Жыл бұрын
если несколько функций вызвано, то мы "уткнемся" не в конец стека, а в некие данные, и как понять к чему они относятся, не зная числа параметров функции?
@pewpewpew8613 Жыл бұрын
@selfedu_rus а почему упремся в конец стека? стек ведь растет в обратную сторону. Увеличивая адрес мы движемся по стеку к его началу. Имея ссылку на начало стек фрейма мы можем начать с первого аргумента и увеличивать адрес пока не уткнемся в начало этого же стек фрейма. Ссылка на начало и будет нашим ограничителем что бы не зайти в предыдущий стек фрейм
@olegkomlev3 ай бұрын
@@pewpewpew8613 Вообще говоря, да. В стековом фрейме хранятся параметры, локальные переменные, адрес возврата и может быть еще какая-то служебная информация, характерная для платформы, на которой работает программа. Функция должна иметь доступ к параметрам и локальным переменным, для этого у ней есть какой-то "якорь" - служебный указатель, отмечающий какое-то место в стеке. Относительно этого указателя и отсчитываются смещения к параметрам и локальным переменным. Например, для конкретной платформы в момент вызова функции состояние стека может быть таким (от дна стека к вершине): параметр_N, параметр_N-1, ...,параметр_1, адрес_возврата, старое_значение_EBP, локальные_переменные, вершина_стека. При этом значение регистра ЕВР указывает на "старое_значение_EBP" - точку, разделяющую параметры и локальные переменные. По значению EBP можно высчитать, где находится адрес возврата, и сравнивать указатель на очередной параметр с этим значением, чтобы понять , кончились параметры или нет. Но это более платформозависимый механизм, тут просто макросами препроцессора не обойтись, нужны вставки в машинных кодах (для доступа к ЕВР, для учета ближняя это или дальняя функция). Нужно учитывать разрядность ОС (8/16/32/64), процессор, тонкости передачи параметров. Теоретически возможно добавить к stdarg какую-нибудь функцию va_exist (есть ли еще параметры?), но для каждой платформы придется писать свой вариант этой функции.
@AlekzzzR Жыл бұрын
Скажите, а код компилировался под Windows? Дело в том, что в Linux, va_list - это структура, в которой описываются смещения и границы параметров. Это сделано для защиты стека. Да и спасибо за труд.
@selfedu_rus Жыл бұрын
да, под Windows
@Hippan_ Жыл бұрын
А вот va_arg принимает указатель типа va_list и дескриптор типа(int)...а как можно самому объявить такую функцию чтоб она принимала дескриптор типа?
@weerbox Жыл бұрын
Никак, потому что va_arg, va_copy, va_end, va_start это макросы, а не функции. Хотя Сергей почему то их функциями обзывает.
@olegkomlev3 ай бұрын
@@weerbox Но можно написать свои макросы по образцу stdarg.h
@ГубкаБоб-р8ъ Жыл бұрын
В C нет функций с параметрами по умолчанию? После Python я воспринимал функции с параметрами по умолчанию, как нечто что есть везде "по умолчанию"
@Hippan_ Жыл бұрын
раньше в Си цикла for не было
@selfedu_rus Жыл бұрын
В стандарте C99 таких нет. Но в С++ есть.
@olegkomlev3 ай бұрын
Можно моделировать параметры по умолчанию с помощью вариадических параметров. Создать в функции локальные переменные с начальным значением. При чтении вариадических параметров присвоить этим переменным прочитанные значения. А если параметров нет, то останутся первоначально присвоенные (по умолчанию).
@begidurak Жыл бұрын
а зачем нам это, если по факту все равно нужно передавать в функцию количество поступаемых аргументов?
@kotifnat6 ай бұрын
чтобы не писать sum_2, sum_3 и т д, а написать одну sum которая все проглотит если правильно передать
@old_cucumber38054 ай бұрын
А в чем проблема-то? Вы как человек, создающий логику программы, априори знаете количество передаваемых элементов, иначе Вы бы не вызвали функцию. Если Вам лень считать их, то заведите массив аргументов и передайте количество sizeofом. Если угодно, то можно это воспринимать как неудобный синтаксис, взамен которого Вы получаете мощный инструмент.
@kotifnat4 ай бұрын
@@old_cucumber3805 то есть я создаю программу с вводом пользователя, для суммирования, и я заведомо должен знать кол-во аргументов или что? Я вообще не понял логики. Смысл мне городить велосипед, если в языке есть хороший оптимизированный для работы со стеком инструмент для этих вещей? Или вы думаете что в printf тоже надо было через мапу какую нибудь делать, указывая что я сейчас передал?
@kotifnat4 ай бұрын
@@old_cucumber3805 ну то есть я пишу функцию для взаимодействия с пользователем и должен заведомо знать сколько он напишет символов для сложения? Потом хранить все эти параметры в динамическом массиве, постоянно либо аллоцируя сразу дофига, чтоб все введенное влезло, либо реаллоцируя и тратя куча времени? По моему все же проще пользоваться готовым оптимизированным для работы со стеком инструментом….
@olegkomlev3 ай бұрын
Не обязательно передавать именно количество параметров. Например ,в вариадической функции printf первым параметром передается не количество, а форматная строка, где есть символы % c последующей буквой. Каждый % означает параметр, а буква задает тип параметра. Или можно так задать функцию, которая печатает список ненулевых целых чисел: void print_num(int n,...){ va_list param; va_start(param,n); while(n!=0){ printf("%d ",n); n=va_arg(param,int); } va_end(param); printf(" "); } Здесь первый обязательный параметр передает не количество параметров, а является первым параметром. А последним параметром нужно указывать 0, который не будет выведен. Т.е. можно вызывать функцию: print_num(3,5,7,-4,0); // напечатает 3 5 7 -4 print_num(0); //будет выведена пустая строка print_num(6,0); //напечатает 6 print_num(13,55,0);// напечатает 13 55