C для самых маленьких 5

แชร์
ฝัง
  • เผยแพร่เมื่อ 28 พ.ย. 2024

ความคิดเห็น • 19

  • @МихаилСкворцов-в2г
    @МихаилСкворцов-в2г 7 ปีที่แล้ว

    Спасибо!

  • @TheT735
    @TheT735 7 ปีที่แล้ว

    За видео спасибо! Ждем продолжения :)

  • @ruslanmarkiv7608
    @ruslanmarkiv7608 7 ปีที่แล้ว

    Спасибо большое!
    Хотел сказать что про указатели есть очень хорошее видео Александра Писанца (пусть простит меня если не верно написал его имя или фамилию) так там он более понятно расказавает (не обижайтесь, я не хочу сказать что ви плохо расказиваете) потому что он еще и показивает практические примери.
    Теория с практикой лучше самой теории!
    В видео Александра Писанца сказано что указатели виполняются бистрей и контроллер при работе с указателями делает меньше операций чем даже с переменними - ето так?
    Видео 4:45 можно поподробнее? Как етого избежать? Что нужно учитивать?

    • @flexoalex4168
      @flexoalex4168  7 ปีที่แล้ว

      Действительно, указатели работают быстрее так как идет обращение напрямую к ОЗУ, а точнее к РОН.
      Наезд на стек это когда мы например записываем данные по указателю, а при этом скачем по адресам не следя за ним. В конечном итоге мы залезаем в адреса стека и затираем его.

    • @ruslanmarkiv7608
      @ruslanmarkiv7608 7 ปีที่แล้ว

      А как ми можем себя от етого обезопасить?
      Ето нужно в програме делать какое то ограждение что типа указателям дальше такого то адреса идти нельзя! Или как?

    • @flexoalex4168
      @flexoalex4168  7 ปีที่แล้ว

      Нет. Просто в качестве второго аргумента функции передавать точную длину массива. Если компилятор выделил место для массива, то оно точно не залезло на стек.

    • @ruslanmarkiv7608
      @ruslanmarkiv7608 7 ปีที่แล้ว

      А можете написать на Си как ето виглядит (практически) а то как би понял что надо сделать но не понял как!
      :) Ви уж извините что я такой не понятливий.

    • @flexoalex4168
      @flexoalex4168  7 ปีที่แล้ว

      Передовать функции длину массива. Массив никогда не залезет на стек.

  • @kaysilver8501
    @kaysilver8501 7 ปีที่แล้ว

    как компилятор интерпретирует запись *p++ ? допустим есть функция которая принимает байт в качестве аргумента void func(char); далее я её вызываю в цикле в котором скармливаю ей массив данных и пушу вот так
    p = arr;
    while((*p) != 0x00)
    {
    func(*p++); // с одной стороны функция берет именно данные, но инкремент производит над указателем
    }
    корректно ли вообще так писать?

    • @flexoalex4168
      @flexoalex4168  7 ปีที่แล้ว

      Компилятор выдаст ошибку. Дело в том что p=arr; при условии что arr это массив, полная ерунда. Имя массива это указатель на первый элемент массива. Поэтому перед p нужно поставить звездочку сказав компилятору что это указатель. Так же нужно перед указателем поставить тип такой же как и у массива, чтобы компилятор знал сколько байт в ячейке. Выглядеть будет так: char arr[3] = {0}; массив на 3 ячейки типа char. char *p = arr; вот теперь все будет правильно. Создается указатель *p с типом char и передается ему адрес первого элемента массива. А вот теперь как использовать указатели. *p++ просто увеличит значение в ячейке памяти на 1 по текущему адресу записанному в указателе p. То есть тоже самое что arr[0]++. p++ (без звездочке) увеличит адрес ячейки на величину байт в зависимости от типа. Если был char, то увеличит на 1, если int, то на 2. Так как архитектура 8-ми битная, а int 16 бит, а адресация идет по байтно. char *p = &arr[0] такая запись эквивалентно предыдущий. Только здесь явно указателю передается адрес ячейки массива с индексом 0.

    • @kaysilver8501
      @kaysilver8501 7 ปีที่แล้ว

      *p++ просто увеличит значение в ячейке памяти на 1 по текущему адресу записанному в указателе p.
      Вот и я думаю что должно так работать, а работает в итоге так, что в функцию передаются именно данные массива, на которые указывает указатель, а ++ инкрементирует адрес. Получается неоднозначность, и я не могу понять почему компилятор такое принимает. Вот конкретно та функция которая проходит компиляцию и работает в реальном контроллере, хотя с точки зрения синтаксиса работать не должна. Передает строку в дисплей:
      void _LCD_string_ram(char addr, char *str)
      {
      _LCD_cmd(0x80 + addr);
      while(*str != 0)
      {
      _LCD_data(*str++);
      }

    • @flexoalex4168
      @flexoalex4168  7 ปีที่แล้ว

      А с точки зрения синтаксиса, здесь ошибки нет)))
      Смотри.
      В качестве аргументов передаем адрес и указатель на массив
      void _LCD_string_ram(char addr, char *str)
      {
      Здесь в качестве аргумента передали адрес плюс смещение в памяти ЖК
      _LCD_cmd(0x80 + addr);
      Просто цикл с ожидание нуля
      while(*str != 0)
      {
      А вот тут прикол. В качестве аргумента передается значение первого элемента массива. Например там символ 'A'. Данный символ в ASCII это число 0x41. То есть функция приняла в качестве аргумента указатель на ячейку в памяти с адресом 0x41. Далее функция возьмет из этой ячейки значение и выведет его на дисплей. Затем в цикле увеличится значение первого элемента массива string на 1 и станет равным 0x42. И так до 0xFF. Следующее увеличение даст переполнение ячейки и станет 0x00. Ура цикл закончился.
      _LCD_data(*str++);
      }
      То есть на дисплей будет выведен мусор из памяти находящейся по адресам с 0x41 до 0xFF.

    • @kaysilver8501
      @kaysilver8501 7 ปีที่แล้ว

      А как тогда правильно переписать эту строчку: _LCD_data(*str++); чтобы функция _LCD_data принимала код символа, но инкремент шел именно значения указателя. Нам же надо код символа выводить на дисплей, а проверку делать на равенства символа 0х00, как признака оканчания строки?

    • @flexoalex4168
      @flexoalex4168  7 ปีที่แล้ว

      _LCD_data(*str); // Передали код символа
      str++; // Сдвинулись на следующей символ.