Я читаю книгу под названием «Обучи себя C за 21 день» (я уже выучил Java и C #, поэтому я двигаюсь гораздо быстрее). Я читал главу об указателях, и оператор->
(стрелка) появился без объяснения причин. Я думаю, что он используется для вызова членов и функций (например, эквивалент оператора (точка), но для указателей вместо членов). Но я не совсем уверен..
Могу ли я получить объяснение и пример кода?
Ответы:
foo->bar
эквивалентно(*foo).bar
, то есть он получает член, вызванныйbar
из структуры, на которуюfoo
указывает.источник
->
оператор вообще не понадобился бы, поскольку он был бы эквивалентен гораздо более разборчивомуfoo*.bar
. Также можно было бы избежать всей путаницы функций определения типов со всеми дополнительными скобками.foo*.bar
и то и(*foo).bar
другое эквивалентноfoo->bar
? Как насчетFoo myFoo = *foo; myFoo.bar
?Да это оно.
Это просто точечная версия, когда вы хотите получить доступ к элементам структуры / класса, которые являются указателем, а не ссылкой.
Это оно!
источник
pvar = &var
?a->b
это просто сокращение(*a).b
во всех отношениях (то же самое для функций:a->b()
сокращение от(*a).b()
).источник
Я бы просто добавил к ответам «почему?».
.
стандартный оператор доступа к элементу, который имеет более высокий приоритет, чем*
оператор указателя.Когда вы пытаетесь получить доступ к внутренним объектам структуры и пишете это так,
*foo.bar
компилятор может захотеть получить элемент 'foo' в 'foo' (который является адресом в памяти) и, очевидно, этот простой адрес не имеет никаких членов.Таким образом, вам нужно попросить компилятор сначала разыменовать whith,
(*foo)
а затем получить доступ к элементу member:,(*foo).bar
который немного неуклюже писать, так что хорошие люди придумали сокращенную версию:foo->bar
это своего рода доступ к элементу с помощью оператора указателя.источник
foo->bar
это только сокращение для(*foo).bar
. Это все, что нужно сделать.источник
Здесь , чтобы получить доступ к значениям
i
иj
мы можем использовать переменныеa
и указательp
следующим образом :a.i
,(*p).i
иp->i
все же.Вот
.
«Прямой селектор» и->
«Косвенный селектор».источник
Ну, я тоже должен кое-что добавить. Структура немного отличается от массива, потому что массив является указателем, а структура - нет. Так что будьте осторожны!
Допустим, я пишу этот бесполезный кусок кода:
Здесь указатель
ptr
указывает на адрес ( ! ) Структурной переменной,audi
но кроме адресной структуры также есть кусок данных ( ! )! Первый элемент блока данных имеет тот же адрес, что и сама структура, и вы можете получить его данные, только разыменовав указатель, как этот*ptr
(без скобок) .Но если вы хотите Асесс любого другого члена , чем первый, вы должны добавить условное обозначение , как
.km
,.kph
,.kg
которые являются не более , чем смещение к базовому адресу порции данных ...Но из-за старшинства вы не можете написать
*ptr.kg
как оператор доступа.
оценивается перед оператором разыменования,*
и вы получите,*(ptr.kg)
что невозможно, так как указатель не имеет членов! И компилятор знает это и поэтому выдаст ошибку, например:Вместо этого вы используете это,
(*ptr).kg
и вы заставляете компилятор 1-й разыменования указателя и включить Асесс в порции данных и второго добавления смещения (обозначение) , чтобы выбрать элемент.Проверьте это изображение, которое я сделал:
Но если бы вы имели вложенные члены, этот синтаксис стал бы нечитаемым и, следовательно,
->
был введен. Я думаю, что удобочитаемость является единственной оправданной причиной для его использования, поскольку этоptr->kg
гораздо проще, чем писать(*ptr).kg
.Теперь давайте напишем это по-другому, чтобы вы видели связь более четко.
(*ptr).kg
⟹(*&audi).kg
⟹audi.kg
. Здесь я впервые использовал тот факт, чтоptr
это «адресaudi
», т.&audi
Е. И тот факт, что операторы «ссылка»&
и «разыменование»*
отменяют друг друга.источник
Я должен был сделать небольшое изменение в программе Джека, чтобы заставить ее работать. После объявления структурного указателя pvar укажите его адрес var. Я нашел это решение на странице 242 Программирования Стивена Кочана в C.
Запустите это в vim с помощью следующей команды:
Будет выводить:
источник
%
для представления текущего имени файла.!gcc % && ./a.out
источник
->
Оператор делает код более читаемым , чем*
оператор в некоторых ситуациях.Например: (цитируется по проекту EDK II )
_EFI_BLOCK_IO_PROTOCOL
содержит 4 члена указателя функции.Предположим, у вас есть переменная
struct _EFI_BLOCK_IO_PROTOCOL * pStruct
, и вы хотите использовать старый добрый*
оператор для вызова ее указателя на функцию-член. В итоге вы получите такой код:(*pStruct).ReadBlocks(...arguments...)
Но с
->
оператором вы можете написать так:pStruct->ReadBlocks(...arguments...)
,Который выглядит лучше?
источник
выход 5 5 5
источник
Dot является оператором разыменования и используется для соединения структурной переменной для конкретной записи структуры. Например:
Таким образом, мы можем использовать оператор точки для доступа к структурной переменной
источник
->
. Также на этот вопрос уже 4,5 года.