Как работает и не работает обобщённый указатель void * в C (Си)

Поделиться
HTML-код
  • Опубликовано: 8 фев 2025
  • void * - особый указатель. Он может то, чего не может никто - и не может то, что могут все. Как нам это поможет и при чём тут функциональное программирование? Обсудим и покодим.
    ВНИМАНИЕ: ошибка в коде функции free_regmem() - и по ходу стрима её не обнаружили. А это важно. Потерян инкремент p. Должно быть p++ в конце блока while.

Комментарии • 38

  • @iKumarov
    @iKumarov 8 дней назад

    Может я тупой, но как отработала free_regmem если мы не сдвигали p?

    • @olgapavlova
      @olgapavlova  8 дней назад

      Или я забыла написать p++, что тоже вполне вероятно (сейчас не проверить).
      Проверка утечек на Маке - так себе удовольствие, о чём я подумала с сильным запозданием.
      Спасибо за внимательность!

    • @olgapavlova
      @olgapavlova  8 дней назад +1

      Да, действительно забыла. Ну и leaks обманул.
      Добавила в описание ролика, надеюсь, кто-то заметит.
      Ваш комментарий закреплю.
      Спасибо ещё раз!

    • @anatol2709
      @anatol2709 6 дней назад

      ​@@olgapavlova там еще и REGMEM не удаляется, видимо leaks надо както по другому использовать. Вообще у меня при просмотре возник такой вопрос - а зачем вы используете консоль? Есть же полно инструментов с нормальным гуем, с которыми приятнее и быстрее работать, а в консоле приходится сильно больше кнопок нажимать и скорость с качеством работы падает.

    • @olgapavlova
      @olgapavlova  6 дней назад

      @ С leaks надо разобраться нормально, ага. Я забыла, что с мака транслирую :)
      Про консоль: пока мне не удалось подобрать инструмент удобней лично для себя. По совокупности разных факторов. Но личным опытом поделитесь, конечно - не мне так другому кому поможет.

    • @anatol2709
      @anatol2709 6 дней назад +1

      @@olgapavlova самое удобное что я когда либо использовал, это MSVC. Я посмотрел соседние стримы, и там не сильно дальше хелло ворлд все, для этих целей можно просто онлайн компиляторы использовать. Причина - стрим явно для новичков, и постоянное мелькание непонятного текста, редактирование make файлов, ужасный для неокрепших умов vim и так далее, все это может заметно отвлекать, хоть и выглядит по кулхацкерски. А вести разработку за деньги в консоле можно в 2 случаях - либо если это крутой программер и такая вот девиация у человека (тут я вообще без притензий), либо на удаленной машине с линухом чтото подправить надо, больше не вижу причин.

  • @PavelLaminar
    @PavelLaminar 5 дней назад

    На мой взгляд - неимоверная годнота, большое спасибо, что делитесь. А теперь вопрос ) сама концепция понятна, берем что угодно и возвращаем, что угодно, но для реализации каких-то действий мы всё равно приводим это "что угодно" к определенному типу. В таком случае не проще ли использовать функции с указанием типов принимаемого и возвращаемого значений, тем более в этом случае мы следует принципу - "явное лучше неявного"?

    • @olgapavlova
      @olgapavlova  День назад

      Дело в том, что мы, бывает, не знаем, функции с какими типами к нам прилетят.
      Ведь next бывает у массива, у словаря, у строки, у файла,…
      Это именно приём, позволяющий не думать о типах.
      Конечно, если типы жёстко известны, то нет причин отказываться от их анонсирования, и void * не нужен.
      Про явное и неявное: мне кажется, принципы Python - это нечто ооооочень далёкое от принципов C :) Не случайно эти языки так хорошо друг друга дополняют.

  • @MikeTyukanov
    @MikeTyukanov 5 дней назад

    Спасибо, реально интересно даже хорошо знакомые темы смотреть, просто потому, что отвык от чистого Си.
    Но кое-что все же помню: в Си не надо явно кастить ни войд-указатели к типизированным, ни обратно.
    То есть, в char * w3 = (char *) create_str(&letter_1); (char*) точно так же избыточен, как в каком-нибудь char * str = (char*)malloc(10); (вот в плюсах это понадобилось бы). А (void*), как в return (void*)result; не нужен ни в Си, ни в плюсах.
    Вот где явный каст нужен, это в char c = *(char*)cv; оператор дереференса автоматически кастить не умеет. Но если бы было длинно char *cptr = cv; char c = *cptr; то тут не надо было бы. Поскольку скастить в этом случае короче, так и делают.

  • @TheLordWilex
    @TheLordWilex 8 дней назад

    Кажется у меня появилась новая традиция смотреть в ночь с пятницы на субботу лекцию про C ))
    В самом конце, на 1 часе 17 минуте Вы говорите про упаковку произвольного кол-ва аргументов в функцию и приводите пример кода. Было бы здорово, если Вы остановитесь на этом подробней в следующих лекциях

  • @nordfawkes107
    @nordfawkes107 3 дня назад

    За долгие годы практики пришёл к конструкции "универсальной" функции my_type_or_void funcname(int, int).
    Где первым интом идёт указатель приведённый к типу int, а вторым, если надо, размер данных по указателю. Потом в теле функции приводил первый аргумент к нужному типу данных (число, строка, указатель на структуру, указатель на функцию итд)
    Сразу поясню, это касалось специфики работы, когда вызовы функции и данные слегка менялись по мере написания программы. Или при заимствовании кода между проектами. Возможно решение подходит только мне, просто делюсь опытом.

  • @cdeblog
    @cdeblog 20 часов назад

    Нет никакой договорённости про char * , это просто указатель на область с байтами, не более того, а то как она она используется зависит от алгоритма, если это строковые функции, то они ожидают \0 лишь потому что в си строки должны заканчиваться нулем. Указатель по это ничего не знает. Выделите массив байт (числовых значений) и возьмите указатель, где тут ноль?

  • @DB-zz8zm
    @DB-zz8zm 6 дней назад

    А как же концепция того, что память нужно освобождать как можно раньше?

    • @olgapavlova
      @olgapavlova  6 дней назад

      Знаете, я как-то не вижу, чтобы эту концепцию всерьёз обсуждали в современной литературе. Скорее даже рекомендуют вообще забить на утечки памяти и больше думать о том, чтобы не было фрагментации. Хотя, конечно, тут смотря что и для какого железа писать.

  • @cdeblog
    @cdeblog 20 часов назад

    void * не нужно дополнительно кастовать к другому типу. Равно как и указатель на любой другой тип не нужно кастовать к void *
    1. Всё кастуется само и является валидной конструкцией
    2. В будущем когда код будет развиваться будет меньше проблем если где-то поменяются типы

  • @rayrayray4653
    @rayrayray4653 8 дней назад

    Хорошо)

  • @leonid_konoplin
    @leonid_konoplin 8 дней назад

    Здравствуйте, Ольга. Как можно с Вами связаться? Есть один вопрос и одно пожелание, если Вас не затруднит

    • @olgapavlova
      @olgapavlova  8 дней назад +1

      На почту можно написать: olgapavlova@gmail.com

  • @dmitrydalidovich1753
    @dmitrydalidovich1753 8 дней назад

    каждая ли функция, которая передаётся в качестве параметра другой функции, является колбэком?

    • @olgapavlova
      @olgapavlova  8 дней назад +1

      Смотря что вы с ней там делаете. Если вызываете - да, это формально функция обратного вызова, она же callback function. А если, например, просто проверяете на совпадение с другой функцией (точнее, с указателем) - нет.

  • @Злостный_Двачер
    @Злостный_Двачер 8 дней назад

    Я так и не понял как работает free() с обобщённым указателем? Откуда она знает сколько нужно освобождать ячеек памяти?

    • @olgapavlova
      @olgapavlova  8 дней назад

      Там ошибка. Посмотрите закреплённый комментарий и ветку по нему, пожалуйста. Спасибо за внимательность!

    • @Злостный_Двачер
      @Злостный_Двачер 7 дней назад

      @@olgapavlova Я не про это. Я про слайд на 48:11 там где free(av); av - указатель типа void. Откуда она узнаёт длину освобождаемой переменной?

    • @olgapavlova
      @olgapavlova  7 дней назад

      @ Насколько я знаю (на глубину знаний не претендую), free() работает не напрямую с памятью, а с менеджером динамической памяти. Как бы отдаёт ему команду: «Найди в своём реестре выделенной памяти блок с этим адресом и освободи его». Но тип, под который выделен блок, менеджеру для освобождения не важен (хотя он его и знает).
      Именно поэтому при освобождении памяти типизация указателей не нужна и даже избыточна.

    • @anatol2709
      @anatol2709 6 дней назад

      там идет обращение к куче, куче нужен только указатель на начало выделенной памяти, размер самого блока куче известен. Если интересно, можно начать с вики, статья "Куча (память)"

  • @Carpet-Shark
    @Carpet-Shark День назад

    А сегодня стрим бьіл?

    • @olgapavlova
      @olgapavlova  День назад +1

      Вот только что ролик появился, you are welcome :)

    • @Carpet-Shark
      @Carpet-Shark День назад

      @@olgapavlova Thanks!

  • @mtp7261
    @mtp7261 7 дней назад

    p++

  • @dmitrydalidovich1753
    @dmitrydalidovich1753 8 дней назад

    Разыменование указателя, так и называется

    • @olgapavlova
      @olgapavlova  8 дней назад

      Значит, правильно помнила. Спасибо!