C указатели и ссылки для чайников: точки над i / Хабр

c++ — Чем отличаются ссылки от указателей в С++

Ссылки проще понять в сравнении с указателями. По сути, это те же указатели, но немного измененные.

Напишу только про обычные ссылки («lvalue-ссылки» &). Про «rvalue-ссылки» && — читать отдельно.

  • Ссылки всегда разыменовываются автоматически (после того, как были созданы):

    int x = 0;                   int x = 0;
    int *y = &x;                 int &y = x;
    *y = 42;                     y = 42; // Не нужно разыменование.
    
    • Следствие: Ссылку нельзя «перенацелить» на другой объект, после того, как она создана.

      Если для указателя можно написать y = &z;, то для ссылки присваивание меняет объект, на который она ссылается, а не ее саму.

      • Следствие: Ссылку обязательно инициализировать сразу при создании.

        int *z; /* ок */             int &z; // Ошибка компиляции.
        
      • Следствие: Ссылки не бывают константными.

        Поскольку их и так нельзя менять, дополнительный const не имеет смысла и запрещен.

        int *const x — «x — константный указатель на неконстантный int«. Но int &const x — ошибка компиляции.

        Не путать с const int *x и const int &x — неконстантный указатель/ссылка на константный int. Тут оба варианта легальны.

  • Ссылки инициализируются не адресом, а самим объектом (см. пример выше).

    Разница только в способе записи, эффект на самом деле одинаковый.

    • Следствие: Ссылки не бывают нулевыми.

      Указатель можно инициализировать nullptr — нулевым адресом. А поскольку ссылка инициализируется не адресом, туда указатель не подойдет.

      Попытка создать нулевую ссылку (пример: int *x = nullptr; int &y = *x;) вызывает неопределенное поведение. Но компиляторы обычно никак не защищают от этого (вероятнее всего, крашнет при использовании ссылки, а не при создании).

      Но поскольку это UB (т.е. «undefined behavior», т.е. «неопределенное поведение»), проверки а-ля &ссылка == nullptr не имеют никакого смысла, поскольку могут быть выброшены компилятором как всегда ложные.

И указатели, и ссылки часто используют как параметры функций — когда передавать по значению не хочется (либо потому, что нужно изменить параметр и видеть изменения снаружи функции, либо потому, что тип параметра дорого копировать). Соответственно, чаще всего указатели — для опциональных параметров (вместо которых можно передать ноль), а ссылки — для обязательных.

Чтобы передать в функцию массив, традиционно используют указатель на первый элемент, хотя чисто с точки зрения языка, ссылка на первый элемент ничем не хуже.

Некоторые не любят использовать неконстантные ссылки в параметрах. Дескать, нагляднее писать & при вызове, чтобы сразу видеть, что объект меняется.

  • И указатели и ссылки нельзя инициализировать rvalue (грубо говоря, временными объектами, у которых компилятор не дает взять адрес):

    int *x = &42; // ошибка компиляции, сразу на `&`. 
    int &y = 42; // ошибка компиляции
    
    • Исключение: Ссылки на константные типы — можно.
    const int &z = 42; // ок
    

Дальше идут тонкости.

  • Ссылки продляют время жизни временных объектов.

    const int &x = 42;
    int y = x;
    

    Этот пример легален. Временный объект, на который указывает ссылка, продляет свое время жизни до времени жизни ссылки.

    Но в этом правиле много исключений, например при возврате ссылки из функции это не действует. Никаких принципально новых возможностей эта фича не дает, поэтому проще вообще не пользоваться.

  • Ссылки не являются объектами.

    Это больше формальность в стандарте, и тут нужно объяснение.

    Объект — это просто экземпляр какого-то типа, с именем или без. Например, int x — объект типа int, и 42 — тоже. (Исключение: функции — не объекты.)

    Переменная — это, грубо говоря, объект с именем. int x — переменная, а 42 — нет. (Хотя исключения есть. Например, безымянные параметры функций — тоже переменные.)

    И второе исключение: ссылки — это переменные, но не объекты. Т.е. int &x — переменная но не объект, а int x — одновременно и переменная и объект.

    Поэтому, более точное определение переменной — это «то, что было объявлено (если это не функция)». Т.е.

    x — переменная, если где-то выше есть объявление int x;. А 42 — нет, потому что для нее ничего такого нет.

    • Следствие: Формально, у ссылок нет адресов.

      &ссылка выдает адрес не самой ссылки, а того, на что она указывает (это следует из того, что ссылки разыменовываются автоматически).

      Можно положить ссылку в структуру, и взять адрес структуры. Технически, по этому адресу как раз будет лежать ссылка (в виде указателя), но формально — по этому адресу непонятно что.

      • Следствие: Менять какие-то байтики по «адресу» ссылки — UB.
    • Следствие: Не бывает указателей на ссылки, массивов ссылок.

  • Выражения не могут иметь типы-ссылки.

    Это тоже больше формальность.

    У внимательного читателя мог возникнуть вопрос: Если не бывает объектов-ссылок, то чем будет являться возвращенная из функции ссылка? Ведь не переменной, имени-то у нее нет, и объявлена она не была.

    Сначала поясняю, что такое выражение. Классическое определение — это «операнды, соединенные операторами». Т.е. 1 + 1, (2 * 3) + 4, и т.п. Отдельные операнды — это тоже выражения, например 42 или x (если выше есть int x;).

    Выражение — это часть исходного кода программы (грамматический термин), а не то, что существует в памяти (то — объекты).

    Выражение ссылаются на объекты. Например, 1 + 1 ссылается на временный объект int со значением 2. А x ссылается на объект и переменную int x; (если такая объявлена выше).

    Rvalue и lvalue — это свойства выражений (т.

    н. «категория выражения»), а «временный» и «не временный» — свойства объектов.

    Так вот, выражения не могут иметь типы-ссылки.

    Т.е. если имеем int &x, то выражение x — это lvalue типа int (ссылкой оно быть не может). Аналогично, если есть int y, то выражение y — тоже lvalue типа int.

    Аналогично, если имеем int &x(), то x() — lvalue типа int. А для int y(), y() — rvalue типа int.

правила и примеры. Что такое Present Simple и когда употребляется.

Простое время в английском языке — лучший способ рассказать собеседнику о своих привычках и предпочтениях, о том, что мы умеем делать или делаем каждый день. Это одно из самых часто встречающихся времен в повседневной речи, поэтому важно понять и изучить его с самого начала.

Сегодня поговорим о том, что такое Present Simple Tense, распространенные случаи употребления, узнаем основные правила образования Present Simple, какие существуют маркеры времени и рассмотрим примеры предложений.

Что такое Present Simple?

Это простое настоящее время, обозначающее действие в самом широком смысле этого слова. Одна из самых распространенных и простых форм в английском языке для описания действий.

Действия могут быть связаны с привычками, хобби, ежедневным событием вроде подъема по утрам или чем-то, что случается регулярно.

Как образуется Present Simple?

Нет ничего проще, чем поставить глагол в форму Present Simple. Для этого нужно убрать у глагола в инфинитиве частицу «to» и поставить глагол после подлежащего. Это и есть основное правило Present Simple.

Утверждение:

I / We / You / They + V

She / He / It + V + s (es)

I go to work every day — Я хожу на работу каждый день.

They usually play tennis every weekend

— Они обычно играют в теннис каждые выходные.

She brings me coffee every morning — Она приносит мне кофе каждое утро.

It snows in winter — Зимой идет снег.

ВАЖНО: В Present Simple форма глагола практически всегда совпадает с изначальной. Исключение составляет третье лицо единственного числа (he / she / it) — к нему прибавляется окончание -s:

I ride — She rides

I dream — He dreams

Если глагол оканчивается на -s, -ss, -sh, -ch, -x, -o, то к нему прибавляется окончание -es

I wish — She wishes

I teach — She teaches

Если глагол оканчивается на -y, а ему предшествует согласная, то к нему прибавляется окончание

-es, но -y заменяется на -i

I try — She tries

I fly — He flies

Если глагол оканчивается на -y, а ему предшествует гласная, то к нему также прибавляется окончание -s, но -y не меняется.

I play — She plays

I stay — He stays

Отрицание:

Чтобы составить отрицательное предложение — нужно поставить вспомогательный глагол между подлежащим и глаголом.

I / We / You / They + do not (don’t) + V

She / He / It + does not (doesn’t) + V

I don’t go to school every day — Я не хожу в школу каждый день

They don’t drink beer — Они не пьют пиво

She doesn’t like the weather in London

— Ей не нравится погода в Лондоне

He doesn’t drive the car — Он не водит машину

Отрицание также можно выразить при помощи отрицательных местоимений и наречий.

Nobody speaks Arabic — Никто не говорит по-арабски

I do nothing — Я ничего не делаю

Вопрос:

При составлении вопросительных предложений вспомогательный глагол ставится перед подлежащим и последующим глаголом. Обычно — в начало предложения.

Do + I / we / you / they + V ?

Does + she / he / it  + V ?

Do you like pizza? — Тебе нравится пицца?

Do they play football? — Они играют в футбол?

Does she learn Russian? — Она изучает русский язык?

Does he live in Spain? — Он живет в Испании?

Иногда в вопросительном предложении употребляются question words (вопросительные слова) и фразы, которые помогают задать более точный и корректный вопрос собеседнику.

К таким словам относятся: how long (как долго), why (почему), where (где) и другие. Как и в других временах, они ставятся в самом начале предложения перед вопросительной конструкцией Present Simple.

QW + do (does) + I / We / You / They / She / He / It + V ?

Where does he live in Prague? — Где он живет в Праге?

Why do you drink green tea? — Почему ты пьешь зеленый чай?

Когда в предложении с Present Simple появляется вспомогательный глагол — у основного глагола пропадает окончание -s. Считайте, что это такой своеобразный «магнит», который «перетягивает» к себе это окончание. Это касается отрицательной и вопросительной форм Present Simple.

ВАЖНО: иногда вспомогательный глагол do / does можно встретить и в утвердительных предложениях, чтобы добавить экспрессии и яркости высказыванию.

I do want to try this — Я действительно хочу это попробовать

Mary does know how to cook — Мэри действительно умеет готовить

Глагол to be в Present Simple

Глагол to be (быть) всегда является особенным и его употребление во времени Present Simple зависит от подлежащего. Он имеет 3 разных формы:

  • am (для 1-го лица единственного числа: I)
  • is (для 3-го лица единственного числа: she / he / it)
  • are (для 1-го, 2-го и 3-го лица множественного числа: we / you / they)

I am ready — Я готов

She is ready — Она готова

We are ready — Мы готовы

Когда используется Present Simple?

Present Simple используется в описании действий, которые происходят постоянно, на регулярной

основе, но не привязаны к моменту речи.

Употребление Present Simple уместно в тех случаях, когда мы хотим рассказать о нашей ежедневной рутине, достоверно известных фактах, действиях в широком смысле слова или расписании поездов.

Регулярные, повторяющиеся действия:

I often go to the bar — Я часто хожу в бар

They play music every Sunday — Они играют музыку каждое воскресенье

Действие в широком смысле слова (без привязки к моменту речи):

I live in Dublin — Я живу в Дублине.

She speaks Chinese — Она говорит по-китайски.

Факты, о которых знают все:

The Earth rotates around its axis — Земля вращается вокруг своей оси.

Moscow is the largest city in Russia — Москва самый большой город в России

Будущие действия, которые произойдут согласно расписанию:

The airplane takes off at 4.30 am — Самолет взлетит в 4.30 утра.

The train leaves at 9 pm tomorrow — Поезд отходит завтра в 9 вечера.

Рецепты и инструкции (используется вместо повелительного наклонения):

You push the red button to turn on the radio — Нажмите на красную кнопку, чтобы включить радио

First you turn left and then you go down the street — Сперва поверните налево, затем идите до конца улицы

При перечислении каких-то действий и их определенной последовательности также используется время Present Simple

You take the bus into the city center and then you take a taxi to the restaurant — Вы едете на автобусе до центра города, а затем берете такси до ресторана.

Иногда время Present Simple используется в отношении прошедшего времени. Например, в заголовках газет (указывают на факт произошедшего действия) или в рассказе о событии (когда мы говорим о ком-то и его действиях).

The bus with American tourists crashes in India — В Индии разбился автобус с американскими туристами

I met John last week. He comes to me and says: “Hello, old friend” — На прошлой неделе я встретил Джона. Он подошел ко мне и сказал: «Привет, старый друг»

Маркеры времени Present Simple

Для того, чтобы лучше сориентироваться где и когда употребляются глаголы Present Simple — обратите внимание на особые маркеры в тексте.

Такими «маячками» для Present Simple являются наречия (often, always, usually, etc.) и указатели времени (every day, in the morning, on Fridays, etc.).

She always drinks coffee in the morning — Она всегда пьет кофе по утрам

I usually wake up at 6 am — Обычно я просыпаюсь в 6 утра

They often talk about sport — Они часто говорят о спорте

I check my smartphone every 15 minutes — Я проверяю свой телефон каждые 15 минут

He takes a shower twice a day — Он принимает душ два раза в день

On Mondays we go to the central park — По понедельникам мы ходим в центральный парк

He comes here sometimes — Иногда он приходит сюда

Примеры предложений с Present Simple:

Утвердительные предложения:

I read a book every evening — Я читаю книгу каждый вечер

He likes to be polite — Ему нравится быть вежливым

It takes two hours to fly from Berlin — Полет из Берлина займет два часа

Cats like milk — Кошки любят молоко

Отрицательные предложения:

I don’t buy food in the supermarket — Я не покупаю еду в супермаркете

He doesn’t play piano very well — Он не очень хорошо играет на пианино

They don’t read books — Они не читают книги

Duck don’t eat fish — Утки не едят рыбу

Вопросительные предложения:

Do you live in Paris? — Ты живешь в Париже?

Does she play in a band? — Она играет в группе?

Do you eat fish? — Ты ешь рыбу?

Do they like coffee? — Им нравится кофе?

Понимание указателей и объединенных списков в Python

Почему dummy. next ссылается на cur?

Это не .

Изначально создается дополнительный узел, чтобы после него можно было связать узлы из исходных списков. dummy и cur оба являются именами для этого узла в начале функции.

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

Функция возвращает dummy.next , потому что функция работала путем последовательного связывания узлов после этого узла, поэтому dummy.next ссылается на ( не «указывает на») первый из этих связанных узлов.

, и нет явного перемещения указателя dummy в начало cur, как в языке типа C.

В Python нет указателей . Кроме того, cur является узлом ; у него нет «головы». В этой реализации нет объектов, которые явно представляют весь список — только объекты, представляющие узлы, так что список неявно представляет собой какой-то узел вместе со всеми другими, достижимыми из него.

пустышка начиналась как имя вновь созданного узла. Нет необходимости переназначать фиктивный в качестве имени «головы списка», потому что это было имя для этого узла, никогда не переставало быть именем для этого узла, и этот узел использовался как . предшественник для списка. (Поскольку этот узел на самом деле не является частью предполагаемого результата, мы должны пропустить его при возврате.)

Почему мы обновляем cur дважды в последовательных строках?

Во-первых, важно понимать, что мы этого не делаем. Подробно:

Сначала мы устанавливаем cur.next равным одному из списков, но затем мы устанавливаем сам cur равным тому же списку в следующей строке?

Изменение значения cur.next не то же самое, что установка cur . То же самое происходит, например, с элементами списка:

 a = [1, 2, 3]
б = а
# изменение элемента a БУДЕТ изменить то, что мы видим в b:
а[0] = 4
печать (б)
# ЗАМЕНА `a` НЕ изменит то, что мы видим в b:
a = 'привет, мама' # нам даже не нужно заменять его другим списком
печать (б)
 

Запись b = a не копирует список. Это означает, что b — это другое имя для того же объекта , что и a . Если мы изменим на эту штуку , то, очевидно, мы увидим изменение, если проверим b . Если мы сделаем a именем чего-то другого , тогда это , а не повлияет на b , потому что b по-прежнему является именем того, что было раньше.

Это то же самое, что и настоящие имена — или другие формы обращения — людей в реальном мире. Боб — младший сын Алисы. Когда Боб вырастает, Алиса наблюдает, как растет «мой младший сын», потому что это означает, что он тот же человек. Если Алиса родит еще одного мальчика и обнимет «моего младшего сына», Боб не почувствует объятий, потому что «мой младший сын» уже не означает того же человека.


Я не понимаю, зачем это нужно

Теперь можно рассмотреть назначение кода.

cur — это имя, которое мы используем для «последнего узла списка, который мы создаем».

Поскольку мы добавляем узлы в список для его построения, со временем это должно ссылаться на разные узлы.

Выполняя cur.next = ... , мы связываем еще один узел после узла с именем cur . Это поможет нам составить список, но теперь cur больше не является именем последнего узла, потому что это все еще имя узла, который он называл раньше, и этот узел больше не является последним узлом, потому что мы добавили узел.

Итак, после добавления узла мы переназначаем cur для имени узла, который мы только что добавили.

Понимание указателей — Видеоруководство по C

Из курса: C: Структуры данных, указатели и файловые системы

Понимание указателей

— [Инструктор] Чтобы понять указатели, вы должны изучить переменные. В этом коде вы видите переменную Integer alpha. Сразу вы знаете три вещи об этом. Его тип данных, целое число. Его имя, альфа. И его значение, 27, назначено в строке 7. Вы также можете получить два других информативных факта о переменных в вашем коде. Количество байтов, которое он занимает в памяти, полученное по размеру оператора, который появляется в конце строки 9.. И расположение переменной в памяти, полученное с помощью оператора & в конце строки 10. Соберите и запустите. И здесь вы видите, что целочисленная переменная alpha содержит значение 27, что она занимает четыре байта памяти в этой системе и находится по адресу 0060FEFC. И этот адрес будет отличаться от компьютера к компьютеру, а также на одном и том же компьютере, когда вы запускаете код в разное время. Это не гарантия. Эти два элемента, размер переменной и ее расположение в памяти, связаны с концепцией указателей в языке C. Указатель — это переменная, которая содержит ячейку памяти. Это мое определение. Он избегает использования описания, указатель указывает на адрес, что верно, но лучше сказать, что указатель — это переменная, содержащая ячейку памяти. Место памяти чего? Что ж, указатель содержит ячейку памяти или адрес другой переменной в вашем коде. Поскольку указатель сам по себе является переменной, его можно изменить, каким-то образом изменив адрес. Указатель также может манипулировать данными, хранящимися по адресу, на который он ссылается. Указатели объявляются так же, как и любые другие переменные. У них есть тип данных и имя переменной. При объявлении переменной перед именем ставится звездочка. Теперь это единственный оператор указателя звездочки. Это не оператор умножения. Как и все переменные, указатель должен быть инициализирован перед использованием. Неинициализированный указатель приводит к проблемам. Чтобы инициализировать указатель, вы присваиваете ему адрес другой переменной в вашем коде, которая соответствует типу данных указателя. Итак, int для целых чисел, char для символов и так далее. Оператор амперсанд используется для получения адреса переменной. Возможно, вы видели, как этот оператор используется в функции сканирования F, а также в файле упражнений этого фильма.

Оставить комментарий

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *